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