xref: /llvm-project/flang/unittests/Runtime/Reduction.cpp (revision fc51c7f0cc1abf1679100d71d103fe5d943f580b)
1ffc67bb3SDavid Spickett //===-- flang/unittests/Runtime/Reductions.cpp ----------------------------===//
2ffc67bb3SDavid Spickett //
3ffc67bb3SDavid Spickett // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ffc67bb3SDavid Spickett // See https://llvm.org/LICENSE.txt for license information.
5ffc67bb3SDavid Spickett // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ffc67bb3SDavid Spickett //
7ffc67bb3SDavid Spickett //===----------------------------------------------------------------------===//
8ffc67bb3SDavid Spickett 
9ffc67bb3SDavid Spickett #include "flang/Runtime/reduction.h"
10ffc67bb3SDavid Spickett #include "gtest/gtest.h"
11ffc67bb3SDavid Spickett #include "tools.h"
12ffc67bb3SDavid Spickett #include "flang/Common/float128.h"
13ffc67bb3SDavid Spickett #include "flang/Runtime/allocatable.h"
14ffc67bb3SDavid Spickett #include "flang/Runtime/cpp-type.h"
15ffc67bb3SDavid Spickett #include "flang/Runtime/descriptor.h"
163ada883fSPeter Klausler #include "flang/Runtime/reduce.h"
17ffc67bb3SDavid Spickett #include "flang/Runtime/type-code.h"
18ffc67bb3SDavid Spickett #include <cstdint>
19ffc67bb3SDavid Spickett #include <cstring>
20ffc67bb3SDavid Spickett #include <string>
21ffc67bb3SDavid Spickett #include <vector>
22ffc67bb3SDavid Spickett 
23ffc67bb3SDavid Spickett using namespace Fortran::runtime;
24ffc67bb3SDavid Spickett using Fortran::common::TypeCategory;
25ffc67bb3SDavid Spickett 
26ffc67bb3SDavid Spickett TEST(Reductions, Int4Ops) {
27ffc67bb3SDavid Spickett   auto array{MakeArray<TypeCategory::Integer, 4>(
28ffc67bb3SDavid Spickett       std::vector<int>{2, 3}, std::vector<std::int32_t>{1, 2, 3, 4, 5, 6})};
29ffc67bb3SDavid Spickett   std::int32_t sum{RTNAME(SumInteger4)(*array, __FILE__, __LINE__)};
30ffc67bb3SDavid Spickett   EXPECT_EQ(sum, 21) << sum;
31ffc67bb3SDavid Spickett   std::int32_t all{RTNAME(IAll4)(*array, __FILE__, __LINE__)};
32ffc67bb3SDavid Spickett   EXPECT_EQ(all, 0) << all;
33ffc67bb3SDavid Spickett   std::int32_t any{RTNAME(IAny4)(*array, __FILE__, __LINE__)};
34ffc67bb3SDavid Spickett   EXPECT_EQ(any, 7) << any;
35ffc67bb3SDavid Spickett   std::int32_t eor{RTNAME(IParity4)(*array, __FILE__, __LINE__)};
36ffc67bb3SDavid Spickett   EXPECT_EQ(eor, 7) << eor;
37ffc67bb3SDavid Spickett }
38ffc67bb3SDavid Spickett 
39ffc67bb3SDavid Spickett TEST(Reductions, DimMaskProductInt4) {
40ffc67bb3SDavid Spickett   std::vector<int> shape{2, 3};
41ffc67bb3SDavid Spickett   auto array{MakeArray<TypeCategory::Integer, 4>(
42ffc67bb3SDavid Spickett       shape, std::vector<std::int32_t>{1, 2, 3, 4, 5, 6})};
43ffc67bb3SDavid Spickett   auto mask{MakeArray<TypeCategory::Logical, 1>(
44ffc67bb3SDavid Spickett       shape, std::vector<bool>{true, false, false, true, true, true})};
459e53e772SPeter Klausler   StaticDescriptor<maxRank, true> statDesc;
46ffc67bb3SDavid Spickett   Descriptor &prod{statDesc.descriptor()};
47ffc67bb3SDavid Spickett   RTNAME(ProductDim)(prod, *array, 1, __FILE__, __LINE__, &*mask);
48ffc67bb3SDavid Spickett   EXPECT_EQ(prod.rank(), 1);
49ffc67bb3SDavid Spickett   EXPECT_EQ(prod.GetDimension(0).LowerBound(), 1);
50ffc67bb3SDavid Spickett   EXPECT_EQ(prod.GetDimension(0).Extent(), 3);
51ffc67bb3SDavid Spickett   EXPECT_EQ(*prod.ZeroBasedIndexedElement<std::int32_t>(0), 1);
52ffc67bb3SDavid Spickett   EXPECT_EQ(*prod.ZeroBasedIndexedElement<std::int32_t>(1), 4);
53ffc67bb3SDavid Spickett   EXPECT_EQ(*prod.ZeroBasedIndexedElement<std::int32_t>(2), 30);
54ffc67bb3SDavid Spickett   EXPECT_EQ(RTNAME(SumInteger4)(prod, __FILE__, __LINE__), 35);
55ffc67bb3SDavid Spickett   prod.Destroy();
56ffc67bb3SDavid Spickett }
57ffc67bb3SDavid Spickett 
58ffc67bb3SDavid Spickett TEST(Reductions, DoubleMaxMinNorm2) {
59ffc67bb3SDavid Spickett   std::vector<int> shape{3, 4, 2}; // rows, columns, planes
60ffc67bb3SDavid Spickett   //   0  -3   6  -9     12 -15  18 -21
61ffc67bb3SDavid Spickett   //  -1   4  -7  10    -13  16 -19  22
62ffc67bb3SDavid Spickett   //   2  -5   8 -11     14 -17  20  22   <- note last two are equal to test
63ffc67bb3SDavid Spickett   //   BACK=
64ffc67bb3SDavid Spickett   std::vector<double> rawData{0, -1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12,
65ffc67bb3SDavid Spickett       -13, 14, -15, 16, -17, 18, -19, 20, -21, 22, 22};
66ffc67bb3SDavid Spickett   auto array{MakeArray<TypeCategory::Real, 8>(shape, rawData)};
67ffc67bb3SDavid Spickett   EXPECT_EQ(RTNAME(MaxvalReal8)(*array, __FILE__, __LINE__), 22.0);
68ffc67bb3SDavid Spickett   EXPECT_EQ(RTNAME(MinvalReal8)(*array, __FILE__, __LINE__), -21.0);
69ffc67bb3SDavid Spickett   double naiveNorm2{0};
70ffc67bb3SDavid Spickett   for (auto x : rawData) {
71ffc67bb3SDavid Spickett     naiveNorm2 += x * x;
72ffc67bb3SDavid Spickett   }
73ffc67bb3SDavid Spickett   naiveNorm2 = std::sqrt(naiveNorm2);
74ffc67bb3SDavid Spickett   double norm2Error{
75ffc67bb3SDavid Spickett       std::abs(naiveNorm2 - RTNAME(Norm2_8)(*array, __FILE__, __LINE__))};
76ffc67bb3SDavid Spickett   EXPECT_LE(norm2Error, 0.000001 * naiveNorm2);
77ffc67bb3SDavid Spickett   StaticDescriptor<2, true> statDesc;
78ffc67bb3SDavid Spickett   Descriptor &loc{statDesc.descriptor()};
79ffc67bb3SDavid Spickett   RTNAME(MaxlocReal8)
80ffc67bb3SDavid Spickett   (loc, *array, /*KIND=*/8, __FILE__, __LINE__, /*MASK=*/nullptr,
81ffc67bb3SDavid Spickett       /*BACK=*/false);
82ffc67bb3SDavid Spickett   EXPECT_EQ(loc.rank(), 1);
83ffc67bb3SDavid Spickett   EXPECT_EQ(loc.type().raw(), (TypeCode{TypeCategory::Integer, 8}.raw()));
84ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(0).LowerBound(), 1);
85ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(0).Extent(), 3);
86ffc67bb3SDavid Spickett   EXPECT_EQ(
87ffc67bb3SDavid Spickett       *array->Element<double>(loc.ZeroBasedIndexedElement<SubscriptValue>(0)),
88ffc67bb3SDavid Spickett       22.0);
89ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int64_t>(0), 2);
90ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int64_t>(1), 4);
91ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int64_t>(2), 2);
92ffc67bb3SDavid Spickett   loc.Destroy();
93ffc67bb3SDavid Spickett   RTNAME(MaxlocReal8)
94ffc67bb3SDavid Spickett   (loc, *array, /*KIND=*/8, __FILE__, __LINE__, /*MASK=*/nullptr,
95ffc67bb3SDavid Spickett       /*BACK=*/true);
96ffc67bb3SDavid Spickett   EXPECT_EQ(loc.rank(), 1);
97ffc67bb3SDavid Spickett   EXPECT_EQ(loc.type().raw(), (TypeCode{TypeCategory::Integer, 8}.raw()));
98ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(0).LowerBound(), 1);
99ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(0).Extent(), 3);
100ffc67bb3SDavid Spickett   EXPECT_EQ(
101ffc67bb3SDavid Spickett       *array->Element<double>(loc.ZeroBasedIndexedElement<SubscriptValue>(0)),
102ffc67bb3SDavid Spickett       22.0);
103ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int64_t>(0), 3);
104ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int64_t>(1), 4);
105ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int64_t>(2), 2);
106ffc67bb3SDavid Spickett   loc.Destroy();
107ffc67bb3SDavid Spickett   RTNAME(MinlocDim)
108ffc67bb3SDavid Spickett   (loc, *array, /*KIND=*/2, /*DIM=*/1, __FILE__, __LINE__, /*MASK=*/nullptr,
109ffc67bb3SDavid Spickett       /*BACK=*/false);
110ffc67bb3SDavid Spickett   EXPECT_EQ(loc.rank(), 2);
111ffc67bb3SDavid Spickett   EXPECT_EQ(loc.type().raw(), (TypeCode{TypeCategory::Integer, 2}.raw()));
112ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(0).LowerBound(), 1);
113ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(0).Extent(), 4);
114ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(1).LowerBound(), 1);
115ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(1).Extent(), 2);
116ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(0), 2); // -1
117ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(1), 3); // -5
118ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(2), 2); // -2
119ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(3), 3); // -11
120ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(4), 2); // -13
121ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(5), 3); // -17
122ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(6), 2); // -19
123ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(7), 1); // -21
124ffc67bb3SDavid Spickett   loc.Destroy();
125ffc67bb3SDavid Spickett   auto mask{MakeArray<TypeCategory::Logical, 1>(shape,
126ffc67bb3SDavid Spickett       std::vector<bool>{false, false, false, false, false, true, false, true,
127ffc67bb3SDavid Spickett           false, false, true, true, true, false, false, true, false, true, true,
128ffc67bb3SDavid Spickett           true, false, true, true, true})};
129ffc67bb3SDavid Spickett   RTNAME(MaxlocDim)
130ffc67bb3SDavid Spickett   (loc, *array, /*KIND=*/2, /*DIM=*/3, __FILE__, __LINE__, /*MASK=*/&*mask,
131ffc67bb3SDavid Spickett       false);
132ffc67bb3SDavid Spickett   EXPECT_EQ(loc.rank(), 2);
133ffc67bb3SDavid Spickett   EXPECT_EQ(loc.type().raw(), (TypeCode{TypeCategory::Integer, 2}.raw()));
134ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(0).LowerBound(), 1);
135ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(0).Extent(), 3);
136ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(1).LowerBound(), 1);
137ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(1).Extent(), 4);
138ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(0), 2); // 12
139ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(1), 0);
140ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(2), 0);
141ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(3), 2); // -15
142ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(4), 0);
143ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(5), 1); // -5
144ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(6), 2); // 18
145ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(7), 1); // -7
146ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(8), 0);
147ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(9), 2); // -21
148ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(10), 2); // 22
149ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int16_t>(11), 2); // 22
150ffc67bb3SDavid Spickett   loc.Destroy();
151ffc67bb3SDavid Spickett   // Test scalar result for MaxlocDim, MinlocDim, MaxvalDim, MinvalDim.
152ffc67bb3SDavid Spickett   // A scalar result occurs when you have a rank 1 array and dim == 1.
153ffc67bb3SDavid Spickett   std::vector<int> shape1{24};
154ffc67bb3SDavid Spickett   auto array1{MakeArray<TypeCategory::Real, 8>(shape1, rawData)};
1559e53e772SPeter Klausler   StaticDescriptor<2, true> statDesc0[1];
156ffc67bb3SDavid Spickett   Descriptor &scalarResult{statDesc0[0].descriptor()};
157ffc67bb3SDavid Spickett   RTNAME(MaxlocDim)
158ffc67bb3SDavid Spickett   (scalarResult, *array1, /*KIND=*/2, /*DIM=*/1, __FILE__, __LINE__,
159ffc67bb3SDavid Spickett       /*MASK=*/nullptr, /*BACK=*/false);
160ffc67bb3SDavid Spickett   EXPECT_EQ(scalarResult.rank(), 0);
161ffc67bb3SDavid Spickett   EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<std::int16_t>(0), 23);
162ffc67bb3SDavid Spickett   scalarResult.Destroy();
163ffc67bb3SDavid Spickett 
164ffc67bb3SDavid Spickett   // Test .FALSE. scalar MASK argument
165ffc67bb3SDavid Spickett   auto falseMask{MakeArray<TypeCategory::Logical, 4>(
166ffc67bb3SDavid Spickett       std::vector<int>{}, std::vector<std::int32_t>{0})};
167ffc67bb3SDavid Spickett   RTNAME(MaxlocDim)
168ffc67bb3SDavid Spickett   (loc, *array, /*KIND=*/4, /*DIM=*/2, __FILE__, __LINE__,
169ffc67bb3SDavid Spickett       /*MASK=*/&*falseMask, /*BACK=*/false);
170ffc67bb3SDavid Spickett   EXPECT_EQ(loc.rank(), 2);
171ffc67bb3SDavid Spickett   EXPECT_EQ(loc.type().raw(), (TypeCode{TypeCategory::Integer, 4}.raw()));
172ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(0).LowerBound(), 1);
173ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(0).Extent(), 3);
174ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(1).LowerBound(), 1);
175ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(1).Extent(), 2);
176ffc67bb3SDavid Spickett   for (int i{0}; i < 6; ++i) {
177ffc67bb3SDavid Spickett     EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int32_t>(0), 0);
178ffc67bb3SDavid Spickett   }
179ffc67bb3SDavid Spickett   loc.Destroy();
180ffc67bb3SDavid Spickett 
181ffc67bb3SDavid Spickett   // Test .TRUE. scalar MASK argument
182ffc67bb3SDavid Spickett   auto trueMask{MakeArray<TypeCategory::Logical, 4>(
183ffc67bb3SDavid Spickett       std::vector<int>{}, std::vector<std::int32_t>{1})};
184ffc67bb3SDavid Spickett   RTNAME(MaxlocDim)
185ffc67bb3SDavid Spickett   (loc, *array, /*KIND=*/4, /*DIM=*/2, __FILE__, __LINE__,
186ffc67bb3SDavid Spickett       /*MASK=*/&*trueMask, /*BACK=*/false);
187ffc67bb3SDavid Spickett   EXPECT_EQ(loc.rank(), 2);
188ffc67bb3SDavid Spickett   EXPECT_EQ(loc.type().raw(), (TypeCode{TypeCategory::Integer, 4}.raw()));
189ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(0).LowerBound(), 1);
190ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(0).Extent(), 3);
191ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(1).LowerBound(), 1);
192ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(1).Extent(), 2);
193ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int32_t>(0), 3);
194ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int32_t>(1), 4);
195ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int32_t>(2), 3);
196ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int32_t>(3), 3);
197ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int32_t>(4), 4);
198ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int32_t>(5), 4);
199ffc67bb3SDavid Spickett   loc.Destroy();
200ffc67bb3SDavid Spickett 
201ffc67bb3SDavid Spickett   RTNAME(MinlocDim)
202ffc67bb3SDavid Spickett   (scalarResult, *array1, /*KIND=*/2, /*DIM=*/1, __FILE__, __LINE__,
203ffc67bb3SDavid Spickett       /*MASK=*/nullptr, /*BACK=*/true);
204ffc67bb3SDavid Spickett   EXPECT_EQ(scalarResult.rank(), 0);
205ffc67bb3SDavid Spickett   EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<std::int16_t>(0), 22);
206ffc67bb3SDavid Spickett   scalarResult.Destroy();
207ffc67bb3SDavid Spickett 
208ffc67bb3SDavid Spickett   // Test .FALSE. scalar MASK argument
209ffc67bb3SDavid Spickett   RTNAME(MinlocDim)
210ffc67bb3SDavid Spickett   (loc, *array, /*KIND=*/4, /*DIM=*/2, __FILE__, __LINE__,
211ffc67bb3SDavid Spickett       /*MASK=*/&*falseMask, /*BACK=*/false);
212ffc67bb3SDavid Spickett   EXPECT_EQ(loc.rank(), 2);
213ffc67bb3SDavid Spickett   EXPECT_EQ(loc.type().raw(), (TypeCode{TypeCategory::Integer, 4}.raw()));
214ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(0).LowerBound(), 1);
215ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(0).Extent(), 3);
216ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(1).LowerBound(), 1);
217ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(1).Extent(), 2);
218ffc67bb3SDavid Spickett   for (int i{0}; i < 6; ++i) {
219ffc67bb3SDavid Spickett     EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int32_t>(0), 0);
220ffc67bb3SDavid Spickett   }
221ffc67bb3SDavid Spickett   loc.Destroy();
222ffc67bb3SDavid Spickett 
223ffc67bb3SDavid Spickett   // Test .TRUE. scalar MASK argument
224ffc67bb3SDavid Spickett   RTNAME(MinlocDim)
225ffc67bb3SDavid Spickett   (loc, *array, /*KIND=*/4, /*DIM=*/2, __FILE__, __LINE__,
226ffc67bb3SDavid Spickett       /*MASK=*/&*trueMask, /*BACK=*/false);
227ffc67bb3SDavid Spickett   EXPECT_EQ(loc.rank(), 2);
228ffc67bb3SDavid Spickett   EXPECT_EQ(loc.type().raw(), (TypeCode{TypeCategory::Integer, 4}.raw()));
229ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(0).LowerBound(), 1);
230ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(0).Extent(), 3);
231ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(1).LowerBound(), 1);
232ffc67bb3SDavid Spickett   EXPECT_EQ(loc.GetDimension(1).Extent(), 2);
233ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int32_t>(0), 4);
234ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int32_t>(1), 3);
235ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int32_t>(2), 4);
236ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int32_t>(3), 4);
237ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int32_t>(4), 3);
238ffc67bb3SDavid Spickett   EXPECT_EQ(*loc.ZeroBasedIndexedElement<std::int32_t>(5), 2);
239ffc67bb3SDavid Spickett   loc.Destroy();
240ffc67bb3SDavid Spickett 
241ffc67bb3SDavid Spickett   RTNAME(MaxvalDim)
242ffc67bb3SDavid Spickett   (scalarResult, *array1, /*DIM=*/1, __FILE__, __LINE__, /*MASK=*/nullptr);
243ffc67bb3SDavid Spickett   EXPECT_EQ(scalarResult.rank(), 0);
244ffc67bb3SDavid Spickett   EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<double>(0), 22.0);
245ffc67bb3SDavid Spickett   scalarResult.Destroy();
246ffc67bb3SDavid Spickett   RTNAME(MinvalDim)
247ffc67bb3SDavid Spickett   (scalarResult, *array1, /*DIM=*/1, __FILE__, __LINE__, /*MASK=*/nullptr);
248ffc67bb3SDavid Spickett   EXPECT_EQ(scalarResult.rank(), 0);
249ffc67bb3SDavid Spickett   EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<double>(0), -21.0);
250ffc67bb3SDavid Spickett   scalarResult.Destroy();
251ffc67bb3SDavid Spickett }
252ffc67bb3SDavid Spickett 
253ffc67bb3SDavid Spickett TEST(Reductions, Character) {
254ffc67bb3SDavid Spickett   std::vector<int> shape{2, 3};
255ffc67bb3SDavid Spickett   auto array{MakeArray<TypeCategory::Character, 1>(shape,
256ffc67bb3SDavid Spickett       std::vector<std::string>{"abc", "def", "ghi", "jkl", "mno", "abc"}, 3)};
257ffc67bb3SDavid Spickett   StaticDescriptor<1, true> statDesc[2];
258ffc67bb3SDavid Spickett   Descriptor &res{statDesc[0].descriptor()};
259ffc67bb3SDavid Spickett   RTNAME(MaxvalCharacter)(res, *array, __FILE__, __LINE__);
260ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 0);
261ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Character, 1}.raw()));
262ffc67bb3SDavid Spickett   EXPECT_EQ(std::memcmp(res.OffsetElement<char>(), "mno", 3), 0);
263ffc67bb3SDavid Spickett   res.Destroy();
264ffc67bb3SDavid Spickett   RTNAME(MinvalCharacter)(res, *array, __FILE__, __LINE__);
265ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 0);
266ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Character, 1}.raw()));
267ffc67bb3SDavid Spickett   EXPECT_EQ(std::memcmp(res.OffsetElement<char>(), "abc", 3), 0);
268ffc67bb3SDavid Spickett   res.Destroy();
269ffc67bb3SDavid Spickett   RTNAME(MaxlocCharacter)
270ffc67bb3SDavid Spickett   (res, *array, /*KIND=*/4, __FILE__, __LINE__, /*MASK=*/nullptr,
271ffc67bb3SDavid Spickett       /*BACK=*/false);
272ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
273ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 4}.raw()));
274ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
275ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).Extent(), 2);
276ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 1);
277ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 3);
278ffc67bb3SDavid Spickett   res.Destroy();
279ffc67bb3SDavid Spickett   auto mask{MakeArray<TypeCategory::Logical, 1>(
280ffc67bb3SDavid Spickett       shape, std::vector<bool>{false, true, false, true, false, true})};
281ffc67bb3SDavid Spickett   RTNAME(MaxlocCharacter)
282ffc67bb3SDavid Spickett   (res, *array, /*KIND=*/4, __FILE__, __LINE__, /*MASK=*/&*mask,
283ffc67bb3SDavid Spickett       /*BACK=*/false);
284ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
285ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 4}.raw()));
286ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
287ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).Extent(), 2);
288ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 2);
289ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 2);
290ffc67bb3SDavid Spickett   res.Destroy();
291ffc67bb3SDavid Spickett   RTNAME(MinlocCharacter)
292ffc67bb3SDavid Spickett   (res, *array, /*KIND=*/4, __FILE__, __LINE__, /*MASK=*/nullptr,
293ffc67bb3SDavid Spickett       /*BACK=*/false);
294ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
295ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 4}.raw()));
296ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
297ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).Extent(), 2);
298ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 1);
299ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 1);
300ffc67bb3SDavid Spickett   res.Destroy();
301ffc67bb3SDavid Spickett   RTNAME(MinlocCharacter)
302ffc67bb3SDavid Spickett   (res, *array, /*KIND=*/4, __FILE__, __LINE__, /*MASK=*/nullptr,
303ffc67bb3SDavid Spickett       /*BACK=*/true);
304ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
305ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 4}.raw()));
306ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
307ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).Extent(), 2);
308ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 2);
309ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 3);
310ffc67bb3SDavid Spickett   res.Destroy();
311ffc67bb3SDavid Spickett   RTNAME(MinlocCharacter)
312ffc67bb3SDavid Spickett   (res, *array, /*KIND=*/4, __FILE__, __LINE__, /*MASK=*/&*mask,
313ffc67bb3SDavid Spickett       /*BACK=*/true);
314ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
315ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 4}.raw()));
316ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
317ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).Extent(), 2);
318ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 2);
319ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 3);
320ffc67bb3SDavid Spickett   res.Destroy();
321ffc67bb3SDavid Spickett   static const char targetChar[]{"abc"};
322ffc67bb3SDavid Spickett   Descriptor &target{statDesc[1].descriptor()};
323ffc67bb3SDavid Spickett   target.Establish(1, std::strlen(targetChar),
324ffc67bb3SDavid Spickett       const_cast<void *>(static_cast<const void *>(&targetChar)), 0, nullptr,
325ffc67bb3SDavid Spickett       CFI_attribute_pointer);
326ffc67bb3SDavid Spickett   RTNAME(Findloc)
327ffc67bb3SDavid Spickett   (res, *array, target, /*KIND=*/4, __FILE__, __LINE__, nullptr,
328ffc67bb3SDavid Spickett       /*BACK=*/false);
329ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
330ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 4}.raw()));
331ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
332ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).Extent(), 2);
333ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 1);
334ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 1);
335ffc67bb3SDavid Spickett   res.Destroy();
336ffc67bb3SDavid Spickett   RTNAME(Findloc)
337ffc67bb3SDavid Spickett   (res, *array, target, /*KIND=*/4, __FILE__, __LINE__, nullptr, /*BACK=*/true);
338ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
339ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 4}.raw()));
340ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
341ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).Extent(), 2);
342ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 2);
343ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 3);
344ffc67bb3SDavid Spickett   res.Destroy();
345ffc67bb3SDavid Spickett }
346ffc67bb3SDavid Spickett 
347ffc67bb3SDavid Spickett TEST(Reductions, Logical) {
348ffc67bb3SDavid Spickett   std::vector<int> shape{2, 2};
349ffc67bb3SDavid Spickett   auto array{MakeArray<TypeCategory::Logical, 4>(
350ffc67bb3SDavid Spickett       shape, std::vector<std::int32_t>{false, false, true, true})};
351ffc67bb3SDavid Spickett   ASSERT_EQ(array->ElementBytes(), std::size_t{4});
352ffc67bb3SDavid Spickett   EXPECT_EQ(RTNAME(All)(*array, __FILE__, __LINE__), false);
353ffc67bb3SDavid Spickett   EXPECT_EQ(RTNAME(Any)(*array, __FILE__, __LINE__), true);
354ffc67bb3SDavid Spickett   EXPECT_EQ(RTNAME(Parity)(*array, __FILE__, __LINE__), false);
355ffc67bb3SDavid Spickett   EXPECT_EQ(RTNAME(Count)(*array, __FILE__, __LINE__), 2);
356ffc67bb3SDavid Spickett   StaticDescriptor<2, true> statDesc[2];
357ffc67bb3SDavid Spickett   Descriptor &res{statDesc[0].descriptor()};
358ffc67bb3SDavid Spickett   RTNAME(AllDim)(res, *array, /*DIM=*/1, __FILE__, __LINE__);
359ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
360ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Logical, 4}.raw()));
361ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
362ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).Extent(), 2);
363ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 0);
364ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 1);
365ffc67bb3SDavid Spickett   res.Destroy();
366ffc67bb3SDavid Spickett   RTNAME(AllDim)(res, *array, /*DIM=*/2, __FILE__, __LINE__);
367ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
368ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Logical, 4}.raw()));
369ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
370ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).Extent(), 2);
371ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 0);
372ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 0);
373ffc67bb3SDavid Spickett   res.Destroy();
374ffc67bb3SDavid Spickett   // Test scalar result for AllDim.
375ffc67bb3SDavid Spickett   // A scalar result occurs when you have a rank 1 array.
376ffc67bb3SDavid Spickett   std::vector<int> shape1{4};
377ffc67bb3SDavid Spickett   auto array1{MakeArray<TypeCategory::Logical, 4>(
378ffc67bb3SDavid Spickett       shape1, std::vector<std::int32_t>{false, false, true, true})};
379ffc67bb3SDavid Spickett   StaticDescriptor<1, true> statDesc0[1];
380ffc67bb3SDavid Spickett   Descriptor &scalarResult{statDesc0[0].descriptor()};
381ffc67bb3SDavid Spickett   RTNAME(AllDim)(scalarResult, *array1, /*DIM=*/1, __FILE__, __LINE__);
382ffc67bb3SDavid Spickett   EXPECT_EQ(scalarResult.rank(), 0);
383ffc67bb3SDavid Spickett   EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<std::int32_t>(0), 0);
384ffc67bb3SDavid Spickett   scalarResult.Destroy();
385ffc67bb3SDavid Spickett   RTNAME(AnyDim)(res, *array, /*DIM=*/1, __FILE__, __LINE__);
386ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
387ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Logical, 4}.raw()));
388ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
389ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).Extent(), 2);
390ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 0);
391ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 1);
392ffc67bb3SDavid Spickett   res.Destroy();
393ffc67bb3SDavid Spickett   RTNAME(AnyDim)(res, *array, /*DIM=*/2, __FILE__, __LINE__);
394ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
395ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Logical, 4}.raw()));
396ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
397ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).Extent(), 2);
398ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 1);
399ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 1);
400ffc67bb3SDavid Spickett   res.Destroy();
401ffc67bb3SDavid Spickett   // Test scalar result for AnyDim.
402ffc67bb3SDavid Spickett   // A scalar result occurs when you have a rank 1 array.
403ffc67bb3SDavid Spickett   RTNAME(AnyDim)(scalarResult, *array1, /*DIM=*/1, __FILE__, __LINE__);
404ffc67bb3SDavid Spickett   EXPECT_EQ(scalarResult.rank(), 0);
405ffc67bb3SDavid Spickett   EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<std::int32_t>(0), 1);
406ffc67bb3SDavid Spickett   scalarResult.Destroy();
407ffc67bb3SDavid Spickett   RTNAME(ParityDim)(res, *array, /*DIM=*/1, __FILE__, __LINE__);
408ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
409ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Logical, 4}.raw()));
410ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
411ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).Extent(), 2);
412ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 0);
413ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 0);
414ffc67bb3SDavid Spickett   res.Destroy();
415ffc67bb3SDavid Spickett   RTNAME(ParityDim)(res, *array, /*DIM=*/2, __FILE__, __LINE__);
416ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
417ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Logical, 4}.raw()));
418ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
419ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).Extent(), 2);
420ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 1);
421ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 1);
422ffc67bb3SDavid Spickett   res.Destroy();
423ffc67bb3SDavid Spickett   // Test scalar result for ParityDim.
424ffc67bb3SDavid Spickett   // A scalar result occurs when you have a rank 1 array.
425ffc67bb3SDavid Spickett   RTNAME(ParityDim)(scalarResult, *array1, /*DIM=*/1, __FILE__, __LINE__);
426ffc67bb3SDavid Spickett   EXPECT_EQ(scalarResult.rank(), 0);
427ffc67bb3SDavid Spickett   EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<std::int32_t>(0), 0);
428ffc67bb3SDavid Spickett   scalarResult.Destroy();
429ffc67bb3SDavid Spickett   RTNAME(CountDim)(res, *array, /*DIM=*/1, /*KIND=*/4, __FILE__, __LINE__);
430ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
431ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 4}.raw()));
432ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
433ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).Extent(), 2);
434ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 0);
435ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 2);
436ffc67bb3SDavid Spickett   res.Destroy();
437ffc67bb3SDavid Spickett   RTNAME(CountDim)(res, *array, /*DIM=*/2, /*KIND=*/8, __FILE__, __LINE__);
438ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
439ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 8}.raw()));
440ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
441ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).Extent(), 2);
442ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int64_t>(0), 1);
443ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int64_t>(1), 1);
444ffc67bb3SDavid Spickett   res.Destroy();
445ffc67bb3SDavid Spickett   // Test scalar result for CountDim.
446ffc67bb3SDavid Spickett   // A scalar result occurs when you have a rank 1 array and dim == 1.
447ffc67bb3SDavid Spickett   RTNAME(CountDim)
448ffc67bb3SDavid Spickett   (scalarResult, *array1, /*DIM=*/1, /*KIND=*/8, __FILE__, __LINE__);
449ffc67bb3SDavid Spickett   EXPECT_EQ(scalarResult.rank(), 0);
450ffc67bb3SDavid Spickett   EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<std::int64_t>(0), 2);
451ffc67bb3SDavid Spickett   scalarResult.Destroy();
452ffc67bb3SDavid Spickett   bool boolValue{false};
453ffc67bb3SDavid Spickett   Descriptor &target{statDesc[1].descriptor()};
454ffc67bb3SDavid Spickett   target.Establish(TypeCategory::Logical, 1, static_cast<void *>(&boolValue), 0,
455ffc67bb3SDavid Spickett       nullptr, CFI_attribute_pointer);
456ffc67bb3SDavid Spickett   RTNAME(Findloc)
457ffc67bb3SDavid Spickett   (res, *array, target, /*KIND=*/4, __FILE__, __LINE__, nullptr,
458ffc67bb3SDavid Spickett       /*BACK=*/false);
459ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
460ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 4}.raw()));
461ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
462ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).Extent(), 2);
463ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 1);
464ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 1);
465ffc67bb3SDavid Spickett   res.Destroy();
466ffc67bb3SDavid Spickett   boolValue = true;
467ffc67bb3SDavid Spickett   RTNAME(Findloc)
468ffc67bb3SDavid Spickett   (res, *array, target, /*KIND=*/4, __FILE__, __LINE__, nullptr, /*BACK=*/true);
469ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
470ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 4}.raw()));
471ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
472ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).Extent(), 2);
473ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 2);
474ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 2);
475ffc67bb3SDavid Spickett   res.Destroy();
476ffc67bb3SDavid Spickett }
477ffc67bb3SDavid Spickett 
478ffc67bb3SDavid Spickett TEST(Reductions, FindlocNumeric) {
479ffc67bb3SDavid Spickett   std::vector<int> shape{2, 3};
480ffc67bb3SDavid Spickett   auto realArray{MakeArray<TypeCategory::Real, 8>(shape,
481ffc67bb3SDavid Spickett       std::vector<double>{0.0, -0.0, 1.0, 3.14,
482ffc67bb3SDavid Spickett           std::numeric_limits<double>::quiet_NaN(),
483ffc67bb3SDavid Spickett           std::numeric_limits<double>::infinity()})};
484ffc67bb3SDavid Spickett   ASSERT_EQ(realArray->ElementBytes(), sizeof(double));
485ffc67bb3SDavid Spickett   StaticDescriptor<2, true> statDesc[2];
486ffc67bb3SDavid Spickett   Descriptor &res{statDesc[0].descriptor()};
487ffc67bb3SDavid Spickett   // Find the first zero
488ffc67bb3SDavid Spickett   Descriptor &target{statDesc[1].descriptor()};
489ffc67bb3SDavid Spickett   double value{0.0};
490ffc67bb3SDavid Spickett   target.Establish(TypeCategory::Real, 8, static_cast<void *>(&value), 0,
491ffc67bb3SDavid Spickett       nullptr, CFI_attribute_pointer);
492ffc67bb3SDavid Spickett   RTNAME(Findloc)
493ffc67bb3SDavid Spickett   (res, *realArray, target, 8, __FILE__, __LINE__, nullptr, /*BACK=*/false);
494ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
495ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 8}.raw()));
496ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
497ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).UpperBound(), 2);
498ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(0), 1);
499ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(1), 1);
500ffc67bb3SDavid Spickett   res.Destroy();
501ffc67bb3SDavid Spickett   // Find last zero (even though it's negative)
502ffc67bb3SDavid Spickett   RTNAME(Findloc)
503ffc67bb3SDavid Spickett   (res, *realArray, target, 8, __FILE__, __LINE__, nullptr, /*BACK=*/true);
504ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
505ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 8}.raw()));
506ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
507ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).UpperBound(), 2);
508ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(0), 2);
509ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(1), 1);
510ffc67bb3SDavid Spickett   res.Destroy();
511ffc67bb3SDavid Spickett   // Find the +Inf
512ffc67bb3SDavid Spickett   value = std::numeric_limits<double>::infinity();
513ffc67bb3SDavid Spickett   RTNAME(Findloc)
514ffc67bb3SDavid Spickett   (res, *realArray, target, 8, __FILE__, __LINE__, nullptr, /*BACK=*/false);
515ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
516ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 8}.raw()));
517ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
518ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).UpperBound(), 2);
519ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(0), 2);
520ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(1), 3);
521ffc67bb3SDavid Spickett   res.Destroy();
522ffc67bb3SDavid Spickett   // Ensure that we can't find a NaN
523ffc67bb3SDavid Spickett   value = std::numeric_limits<double>::quiet_NaN();
524ffc67bb3SDavid Spickett   RTNAME(Findloc)
525ffc67bb3SDavid Spickett   (res, *realArray, target, 8, __FILE__, __LINE__, nullptr, /*BACK=*/false);
526ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
527ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 8}.raw()));
528ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
529ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).UpperBound(), 2);
530ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(0), 0);
531ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(1), 0);
532ffc67bb3SDavid Spickett   res.Destroy();
533ffc67bb3SDavid Spickett   // Find a value of a distinct type
534ffc67bb3SDavid Spickett   int intValue{1};
535ffc67bb3SDavid Spickett   target.Establish(TypeCategory::Integer, 4, static_cast<void *>(&intValue), 0,
536ffc67bb3SDavid Spickett       nullptr, CFI_attribute_pointer);
537ffc67bb3SDavid Spickett   RTNAME(Findloc)
538ffc67bb3SDavid Spickett   (res, *realArray, target, 8, __FILE__, __LINE__, nullptr, /*BACK=*/false);
539ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
540ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 8}.raw()));
541ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
542ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).UpperBound(), 2);
543ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(0), 1);
544ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(1), 2);
545ffc67bb3SDavid Spickett   res.Destroy();
546ffc67bb3SDavid Spickett   // Partial reductions
547ffc67bb3SDavid Spickett   value = 1.0;
548ffc67bb3SDavid Spickett   target.Establish(TypeCategory::Real, 8, static_cast<void *>(&value), 0,
549ffc67bb3SDavid Spickett       nullptr, CFI_attribute_pointer);
550ffc67bb3SDavid Spickett   RTNAME(FindlocDim)
551ffc67bb3SDavid Spickett   (res, *realArray, target, 8, /*DIM=*/1, __FILE__, __LINE__, nullptr,
552ffc67bb3SDavid Spickett       /*BACK=*/false);
553ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
554ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 8}.raw()));
555ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
556ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).UpperBound(), 3);
557ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(0), 0);
558ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(1), 1);
559ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(2), 0);
560ffc67bb3SDavid Spickett   res.Destroy();
561ffc67bb3SDavid Spickett   RTNAME(FindlocDim)
562ffc67bb3SDavid Spickett   (res, *realArray, target, 8, /*DIM=*/2, __FILE__, __LINE__, nullptr,
563ffc67bb3SDavid Spickett       /*BACK=*/true);
564ffc67bb3SDavid Spickett   EXPECT_EQ(res.rank(), 1);
565ffc67bb3SDavid Spickett   EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 8}.raw()));
566ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
567ffc67bb3SDavid Spickett   EXPECT_EQ(res.GetDimension(0).UpperBound(), 2);
568ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(0), 2);
569ffc67bb3SDavid Spickett   EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(1), 0);
570ffc67bb3SDavid Spickett   res.Destroy();
571ffc67bb3SDavid Spickett   // Test scalar result for FindlocDim.
572ffc67bb3SDavid Spickett   // A scalar result occurs when you have a rank 1 array, value, and dim == 1.
573ffc67bb3SDavid Spickett   std::vector<int> shape1{6};
574ffc67bb3SDavid Spickett   auto realArray1{MakeArray<TypeCategory::Real, 8>(shape1,
575ffc67bb3SDavid Spickett       std::vector<double>{0.0, -0.0, 1.0, 3.14,
576ffc67bb3SDavid Spickett           std::numeric_limits<double>::quiet_NaN(),
577ffc67bb3SDavid Spickett           std::numeric_limits<double>::infinity()})};
578ffc67bb3SDavid Spickett   StaticDescriptor<1, true> statDesc0[1];
579ffc67bb3SDavid Spickett   Descriptor &scalarResult{statDesc0[0].descriptor()};
580ffc67bb3SDavid Spickett   RTNAME(FindlocDim)
581ffc67bb3SDavid Spickett   (scalarResult, *realArray1, target, 8, /*DIM=*/1, __FILE__, __LINE__, nullptr,
582ffc67bb3SDavid Spickett       /*BACK=*/false);
583ffc67bb3SDavid Spickett   EXPECT_EQ(scalarResult.rank(), 0);
584ffc67bb3SDavid Spickett   EXPECT_EQ(*scalarResult.ZeroBasedIndexedElement<SubscriptValue>(0), 3);
585ffc67bb3SDavid Spickett   scalarResult.Destroy();
586ffc67bb3SDavid Spickett }
587ffc67bb3SDavid Spickett 
588ffc67bb3SDavid Spickett TEST(Reductions, DotProduct) {
589ffc67bb3SDavid Spickett   auto realVector{MakeArray<TypeCategory::Real, 8>(
590ffc67bb3SDavid Spickett       std::vector<int>{4}, std::vector<double>{0.0, -0.0, 1.0, -2.0})};
591ffc67bb3SDavid Spickett   EXPECT_EQ(
592ffc67bb3SDavid Spickett       RTNAME(DotProductReal8)(*realVector, *realVector, __FILE__, __LINE__),
593ffc67bb3SDavid Spickett       5.0);
594ffc67bb3SDavid Spickett   auto complexVector{MakeArray<TypeCategory::Complex, 4>(std::vector<int>{4},
595ffc67bb3SDavid Spickett       std::vector<std::complex<float>>{
596ffc67bb3SDavid Spickett           {0.0}, {-0.0, -0.0}, {1.0, -2.0}, {-2.0, 4.0}})};
597ffc67bb3SDavid Spickett   std::complex<double> result8;
598ffc67bb3SDavid Spickett   RTNAME(CppDotProductComplex8)
599ffc67bb3SDavid Spickett   (result8, *realVector, *complexVector, __FILE__, __LINE__);
600ffc67bb3SDavid Spickett   EXPECT_EQ(result8, (std::complex<double>{5.0, -10.0}));
601ffc67bb3SDavid Spickett   RTNAME(CppDotProductComplex8)
602ffc67bb3SDavid Spickett   (result8, *complexVector, *realVector, __FILE__, __LINE__);
603ffc67bb3SDavid Spickett   EXPECT_EQ(result8, (std::complex<double>{5.0, 10.0}));
604ffc67bb3SDavid Spickett   std::complex<float> result4;
605ffc67bb3SDavid Spickett   RTNAME(CppDotProductComplex4)
606ffc67bb3SDavid Spickett   (result4, *complexVector, *complexVector, __FILE__, __LINE__);
607ffc67bb3SDavid Spickett   EXPECT_EQ(result4, (std::complex<float>{25.0, 0.0}));
608ffc67bb3SDavid Spickett   auto logicalVector1{MakeArray<TypeCategory::Logical, 1>(
609ffc67bb3SDavid Spickett       std::vector<int>{4}, std::vector<bool>{false, false, true, true})};
610ffc67bb3SDavid Spickett   EXPECT_TRUE(RTNAME(DotProductLogical)(
611ffc67bb3SDavid Spickett       *logicalVector1, *logicalVector1, __FILE__, __LINE__));
612ffc67bb3SDavid Spickett   auto logicalVector2{MakeArray<TypeCategory::Logical, 1>(
613ffc67bb3SDavid Spickett       std::vector<int>{4}, std::vector<bool>{true, true, false, false})};
614ffc67bb3SDavid Spickett   EXPECT_TRUE(RTNAME(DotProductLogical)(
615ffc67bb3SDavid Spickett       *logicalVector2, *logicalVector2, __FILE__, __LINE__));
616ffc67bb3SDavid Spickett   EXPECT_FALSE(RTNAME(DotProductLogical)(
617ffc67bb3SDavid Spickett       *logicalVector1, *logicalVector2, __FILE__, __LINE__));
618ffc67bb3SDavid Spickett   EXPECT_FALSE(RTNAME(DotProductLogical)(
619ffc67bb3SDavid Spickett       *logicalVector2, *logicalVector1, __FILE__, __LINE__));
620ffc67bb3SDavid Spickett }
621ffc67bb3SDavid Spickett 
622*fc51c7f0SSlava Zakharin #if HAS_LDBL128 || HAS_FLOAT128
623ffc67bb3SDavid Spickett TEST(Reductions, ExtremaReal16) {
624ffc67bb3SDavid Spickett   // The identity value for Min/Maxval for REAL(16) was mistakenly
625ffc67bb3SDavid Spickett   // set to 0.0.
626ffc67bb3SDavid Spickett   using ElemType = CppTypeFor<TypeCategory::Real, 16>;
627ffc67bb3SDavid Spickett   std::vector<int> shape{3};
628ffc67bb3SDavid Spickett   //   1.0  2.0  3.0
629ffc67bb3SDavid Spickett   std::vector<ElemType> rawMinData{1.0, 2.0, 3.0};
630ffc67bb3SDavid Spickett   auto minArray{MakeArray<TypeCategory::Real, 16>(shape, rawMinData)};
631ffc67bb3SDavid Spickett   EXPECT_EQ(RTNAME(MinvalReal16)(*minArray, __FILE__, __LINE__), 1.0);
632ffc67bb3SDavid Spickett   //   -1.0  -2.0  -3.0
633ffc67bb3SDavid Spickett   std::vector<ElemType> rawMaxData{-1.0, -2.0, -3.0};
634ffc67bb3SDavid Spickett   auto maxArray{MakeArray<TypeCategory::Real, 16>(shape, rawMaxData)};
635ffc67bb3SDavid Spickett   EXPECT_EQ(RTNAME(MaxvalReal16)(*maxArray, __FILE__, __LINE__), -1.0);
636ffc67bb3SDavid Spickett }
637*fc51c7f0SSlava Zakharin #endif // HAS_LDBL128 || HAS_FLOAT128
6383ada883fSPeter Klausler 
6393ada883fSPeter Klausler static std::int32_t IAdd(const std::int32_t *x, const std::int32_t *y) {
6403ada883fSPeter Klausler   return *x + *y;
6413ada883fSPeter Klausler }
6423ada883fSPeter Klausler 
6433ada883fSPeter Klausler static std::int32_t IMultiply(const std::int32_t *x, const std::int32_t *y) {
6443ada883fSPeter Klausler   return *x * *y;
6453ada883fSPeter Klausler }
6463ada883fSPeter Klausler 
6473ada883fSPeter Klausler TEST(Reductions, ReduceInt4) {
6483ada883fSPeter Klausler   auto intVector{MakeArray<TypeCategory::Integer, 4>(
6493ada883fSPeter Klausler       std::vector<int>{4}, std::vector<std::int32_t>{1, 2, 3, 4})};
6503ada883fSPeter Klausler   EXPECT_EQ(
651f8fc883dSPeter Klausler       RTNAME(ReduceInteger4Ref)(*intVector, IAdd, __FILE__, __LINE__), 10);
652f8fc883dSPeter Klausler   EXPECT_EQ(
653f8fc883dSPeter Klausler       RTNAME(ReduceInteger4Ref)(*intVector, IMultiply, __FILE__, __LINE__), 24);
6543ada883fSPeter Klausler }
6553ada883fSPeter Klausler TEST(Reductions, ReduceInt4Dim) {
6563ada883fSPeter Klausler   auto intMatrix{MakeArray<TypeCategory::Integer, 4>(
6573ada883fSPeter Klausler       std::vector<int>{2, 2}, std::vector<std::int32_t>{1, 2, 3, 4})};
6589e53e772SPeter Klausler   StaticDescriptor<2, true> statDesc;
6593ada883fSPeter Klausler   Descriptor &sums{statDesc.descriptor()};
660f8fc883dSPeter Klausler   RTNAME(ReduceInteger4DimRef)(sums, *intMatrix, IAdd, __FILE__, __LINE__, 1);
6613ada883fSPeter Klausler   EXPECT_EQ(sums.rank(), 1);
6623ada883fSPeter Klausler   EXPECT_EQ(sums.GetDimension(0).LowerBound(), 1);
6633ada883fSPeter Klausler   EXPECT_EQ(sums.GetDimension(0).Extent(), 2);
6643ada883fSPeter Klausler   EXPECT_EQ(*sums.ZeroBasedIndexedElement<std::int32_t>(0), 3);
6653ada883fSPeter Klausler   EXPECT_EQ(*sums.ZeroBasedIndexedElement<std::int32_t>(1), 7);
6663ada883fSPeter Klausler   sums.Destroy();
667f8fc883dSPeter Klausler   RTNAME(ReduceInteger4DimRef)(sums, *intMatrix, IAdd, __FILE__, __LINE__, 2);
6683ada883fSPeter Klausler   EXPECT_EQ(sums.rank(), 1);
6693ada883fSPeter Klausler   EXPECT_EQ(sums.GetDimension(0).LowerBound(), 1);
6703ada883fSPeter Klausler   EXPECT_EQ(sums.GetDimension(0).Extent(), 2);
6713ada883fSPeter Klausler   EXPECT_EQ(*sums.ZeroBasedIndexedElement<std::int32_t>(0), 4);
6723ada883fSPeter Klausler   EXPECT_EQ(*sums.ZeroBasedIndexedElement<std::int32_t>(1), 6);
6733ada883fSPeter Klausler   sums.Destroy();
6743ada883fSPeter Klausler }
675