[flang] Implement IPARITY, PARITY, and FINDLOC reductions
Define APIs for, and implement, these three more recently-introduced standard reduction transformational intrinsic functions to the runtime. Differential Revision: https://reviews.llvm.org/D100863
This commit is contained in:
parent
f2da1f68d8
commit
8d672c0b3e
File diff suppressed because it is too large
Load diff
|
@ -24,8 +24,8 @@ namespace Fortran::runtime {
|
|||
extern "C" {
|
||||
|
||||
// Reductions that are known to return scalars have per-type entry
|
||||
// points. These cover the casse that either have no DIM=
|
||||
// argument, or have an argument rank of 1. Pass 0 for no DIM=
|
||||
// points. These cover the cases that either have no DIM=
|
||||
// argument or have an argument rank of 1. Pass 0 for no DIM=
|
||||
// or the value of the DIM= argument so that it may be checked.
|
||||
// The data type in the descriptor is checked against the expected
|
||||
// return type.
|
||||
|
@ -144,20 +144,42 @@ void RTNAME(CppProductComplex16)(std::complex<long double> &,
|
|||
void RTNAME(ProductDim)(Descriptor &result, const Descriptor &array, int dim,
|
||||
const char *source, int line, const Descriptor *mask = nullptr);
|
||||
|
||||
// MAXLOC and MINLOC
|
||||
// IPARITY()
|
||||
std::int8_t RTNAME(IParity1)(const Descriptor &, const char *source, int line,
|
||||
int dim = 0, const Descriptor *mask = nullptr);
|
||||
std::int16_t RTNAME(IParity2)(const Descriptor &, const char *source, int line,
|
||||
int dim = 0, const Descriptor *mask = nullptr);
|
||||
std::int32_t RTNAME(IParity4)(const Descriptor &, const char *source, int line,
|
||||
int dim = 0, const Descriptor *mask = nullptr);
|
||||
std::int64_t RTNAME(IParity8)(const Descriptor &, const char *source, int line,
|
||||
int dim = 0, const Descriptor *mask = nullptr);
|
||||
#ifdef __SIZEOF_INT128__
|
||||
common::int128_t RTNAME(IParity16)(const Descriptor &, const char *source,
|
||||
int line, int dim = 0, const Descriptor *mask = nullptr);
|
||||
#endif
|
||||
void RTNAME(IParityDim)(Descriptor &result, const Descriptor &array, int dim,
|
||||
const char *source, int line, const Descriptor *mask = nullptr);
|
||||
|
||||
// FINDLOC, MAXLOC, & MINLOC
|
||||
// These return allocated arrays in the supplied descriptor.
|
||||
// The default value for KIND= should be the default INTEGER in effect at
|
||||
// compilation time.
|
||||
void RTNAME(Maxloc)(Descriptor &, const Descriptor &, int kind,
|
||||
void RTNAME(Findloc)(Descriptor &, const Descriptor &x,
|
||||
const Descriptor &target, int kind, const char *source, int line,
|
||||
const Descriptor *mask = nullptr, bool back = false);
|
||||
void RTNAME(FindlocDim)(Descriptor &, const Descriptor &x,
|
||||
const Descriptor &target, int kind, int dim, const char *source, int line,
|
||||
const Descriptor *mask = nullptr, bool back = false);
|
||||
void RTNAME(Maxloc)(Descriptor &, const Descriptor &x, int kind,
|
||||
const char *source, int line, const Descriptor *mask = nullptr,
|
||||
bool back = false);
|
||||
void RTNAME(MaxlocDim)(Descriptor &, const Descriptor &, int kind, int dim,
|
||||
void RTNAME(MaxlocDim)(Descriptor &, const Descriptor &x, int kind, int dim,
|
||||
const char *source, int line, const Descriptor *mask = nullptr,
|
||||
bool back = false);
|
||||
void RTNAME(Minloc)(Descriptor &, const Descriptor &, int kind,
|
||||
void RTNAME(Minloc)(Descriptor &, const Descriptor &x, int kind,
|
||||
const char *source, int line, const Descriptor *mask = nullptr,
|
||||
bool back = false);
|
||||
void RTNAME(MinlocDim)(Descriptor &, const Descriptor &, int kind, int dim,
|
||||
void RTNAME(MinlocDim)(Descriptor &, const Descriptor &x, int kind, int dim,
|
||||
const char *source, int line, const Descriptor *mask = nullptr,
|
||||
bool back = false);
|
||||
|
||||
|
@ -221,7 +243,7 @@ void RTNAME(MaxvalDim)(Descriptor &, const Descriptor &, int dim,
|
|||
void RTNAME(MinvalDim)(Descriptor &, const Descriptor &, int dim,
|
||||
const char *source, int line, const Descriptor *mask = nullptr);
|
||||
|
||||
// ALL, ANY, & COUNT logical reductions
|
||||
// ALL, ANY, COUNT, & PARITY logical reductions
|
||||
bool RTNAME(All)(const Descriptor &, const char *source, int line, int dim = 0);
|
||||
void RTNAME(AllDim)(Descriptor &result, const Descriptor &, int dim,
|
||||
const char *source, int line);
|
||||
|
@ -232,6 +254,10 @@ std::int64_t RTNAME(Count)(
|
|||
const Descriptor &, const char *source, int line, int dim = 0);
|
||||
void RTNAME(CountDim)(Descriptor &result, const Descriptor &, int dim, int kind,
|
||||
const char *source, int line);
|
||||
bool RTNAME(Parity)(
|
||||
const Descriptor &, const char *source, int line, int dim = 0);
|
||||
void RTNAME(ParityDim)(Descriptor &result, const Descriptor &, int dim,
|
||||
const char *source, int line);
|
||||
|
||||
} // extern "C"
|
||||
} // namespace Fortran::runtime
|
||||
|
|
|
@ -24,6 +24,10 @@ public:
|
|||
Terminator(const Terminator &) = default;
|
||||
explicit Terminator(const char *sourceFileName, int sourceLine = 0)
|
||||
: sourceFileName_{sourceFileName}, sourceLine_{sourceLine} {}
|
||||
|
||||
const char *sourceFileName() const { return sourceFileName_; }
|
||||
int sourceLine() const { return sourceLine_; }
|
||||
|
||||
void SetLocation(const char *sourceFileName = nullptr, int sourceLine = 0) {
|
||||
sourceFileName_ = sourceFileName;
|
||||
sourceLine_ = sourceLine;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "descriptor.h"
|
||||
#include "memory.h"
|
||||
#include "terminator.h"
|
||||
#include "flang/Common/long-double.h"
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <type_traits>
|
||||
|
@ -101,5 +102,83 @@ inline bool SetInteger(INT &x, int kind, std::int64_t value) {
|
|||
}
|
||||
}
|
||||
|
||||
// Maps a runtime INTEGER kind value to the appropriate instantiation of
|
||||
// a function object template and calls it with the supplied arguments.
|
||||
template <template <int KIND> class FUNC, typename RESULT, typename... A>
|
||||
inline RESULT ApplyIntegerKind(int kind, Terminator &terminator, A &&...x) {
|
||||
switch (kind) {
|
||||
case 1:
|
||||
return FUNC<1>{}(std::forward<A>(x)...);
|
||||
case 2:
|
||||
return FUNC<2>{}(std::forward<A>(x)...);
|
||||
case 4:
|
||||
return FUNC<4>{}(std::forward<A>(x)...);
|
||||
case 8:
|
||||
return FUNC<8>{}(std::forward<A>(x)...);
|
||||
#ifdef __SIZEOF_INT128__
|
||||
case 16:
|
||||
return FUNC<16>{}(std::forward<A>(x)...);
|
||||
#endif
|
||||
default:
|
||||
terminator.Crash("unsupported INTEGER(KIND=%d)", kind);
|
||||
}
|
||||
}
|
||||
|
||||
template <template <int KIND> class FUNC, typename RESULT, typename... A>
|
||||
inline RESULT ApplyFloatingPointKind(
|
||||
int kind, Terminator &terminator, A &&...x) {
|
||||
switch (kind) {
|
||||
#if 0 // TODO: REAL/COMPLEX (2 & 3)
|
||||
case 2:
|
||||
return FUNC<2>{}(std::forward<A>(x)...);
|
||||
case 3:
|
||||
return FUNC<3>{}(std::forward<A>(x)...);
|
||||
#endif
|
||||
case 4:
|
||||
return FUNC<4>{}(std::forward<A>(x)...);
|
||||
case 8:
|
||||
return FUNC<8>{}(std::forward<A>(x)...);
|
||||
#if LONG_DOUBLE == 80
|
||||
case 10:
|
||||
return FUNC<10>{}(std::forward<A>(x)...);
|
||||
#elif LONG_DOUBLE == 128
|
||||
case 16:
|
||||
return FUNC<16>{}(std::forward<A>(x)...);
|
||||
#endif
|
||||
default:
|
||||
terminator.Crash("unsupported REAL/COMPLEX(KIND=%d)", kind);
|
||||
}
|
||||
}
|
||||
|
||||
template <template <int KIND> class FUNC, typename RESULT, typename... A>
|
||||
inline RESULT ApplyCharacterKind(int kind, Terminator &terminator, A &&...x) {
|
||||
switch (kind) {
|
||||
case 1:
|
||||
return FUNC<1>{}(std::forward<A>(x)...);
|
||||
case 2:
|
||||
return FUNC<2>{}(std::forward<A>(x)...);
|
||||
case 4:
|
||||
return FUNC<4>{}(std::forward<A>(x)...);
|
||||
default:
|
||||
terminator.Crash("unsupported CHARACTER(KIND=%d)", kind);
|
||||
}
|
||||
}
|
||||
|
||||
template <template <int KIND> class FUNC, typename RESULT, typename... A>
|
||||
inline RESULT ApplyLogicalKind(int kind, Terminator &terminator, A &&...x) {
|
||||
switch (kind) {
|
||||
case 1:
|
||||
return FUNC<1>{}(std::forward<A>(x)...);
|
||||
case 2:
|
||||
return FUNC<2>{}(std::forward<A>(x)...);
|
||||
case 4:
|
||||
return FUNC<4>{}(std::forward<A>(x)...);
|
||||
case 8:
|
||||
return FUNC<8>{}(std::forward<A>(x)...);
|
||||
default:
|
||||
terminator.Crash("unsupported LOGICAL(KIND=%d)", kind);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Fortran::runtime
|
||||
#endif // FORTRAN_RUNTIME_TOOLS_H_
|
||||
|
|
|
@ -138,8 +138,8 @@ TEST(Reductions, Character) {
|
|||
std::vector<int> shape{2, 3};
|
||||
auto array{MakeArray<TypeCategory::Character, 1>(shape,
|
||||
std::vector<std::string>{"abc", "def", "ghi", "jkl", "mno", "abc"}, 3)};
|
||||
StaticDescriptor<1> statDesc;
|
||||
Descriptor &res{statDesc.descriptor()};
|
||||
StaticDescriptor<1> statDesc[2];
|
||||
Descriptor &res{statDesc[0].descriptor()};
|
||||
RTNAME(MaxvalCharacter)(res, *array, __FILE__, __LINE__);
|
||||
EXPECT_EQ(res.rank(), 0);
|
||||
EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Character, 1}.raw()));
|
||||
|
@ -202,6 +202,30 @@ TEST(Reductions, Character) {
|
|||
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 2);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 3);
|
||||
res.Destroy();
|
||||
static const char targetChar[]{"abc"};
|
||||
Descriptor &target{statDesc[1].descriptor()};
|
||||
target.Establish(1, std::strlen(targetChar),
|
||||
const_cast<void *>(static_cast<const void *>(&targetChar)), 0, nullptr,
|
||||
CFI_attribute_pointer);
|
||||
RTNAME(Findloc)
|
||||
(res, *array, target, /*KIND=*/4, __FILE__, __LINE__, nullptr,
|
||||
/*BACK=*/false);
|
||||
EXPECT_EQ(res.rank(), 1);
|
||||
EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 4}.raw()));
|
||||
EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
|
||||
EXPECT_EQ(res.GetDimension(0).Extent(), 2);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 1);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 1);
|
||||
res.Destroy();
|
||||
RTNAME(Findloc)
|
||||
(res, *array, target, /*KIND=*/4, __FILE__, __LINE__, nullptr, /*BACK=*/true);
|
||||
EXPECT_EQ(res.rank(), 1);
|
||||
EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 4}.raw()));
|
||||
EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
|
||||
EXPECT_EQ(res.GetDimension(0).Extent(), 2);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 2);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 3);
|
||||
res.Destroy();
|
||||
}
|
||||
|
||||
TEST(Reductions, Logical) {
|
||||
|
@ -211,9 +235,10 @@ TEST(Reductions, Logical) {
|
|||
ASSERT_EQ(array->ElementBytes(), std::size_t{4});
|
||||
EXPECT_EQ(RTNAME(All)(*array, __FILE__, __LINE__), false);
|
||||
EXPECT_EQ(RTNAME(Any)(*array, __FILE__, __LINE__), true);
|
||||
EXPECT_EQ(RTNAME(Parity)(*array, __FILE__, __LINE__), false);
|
||||
EXPECT_EQ(RTNAME(Count)(*array, __FILE__, __LINE__), 2);
|
||||
StaticDescriptor<2> statDesc;
|
||||
Descriptor &res{statDesc.descriptor()};
|
||||
StaticDescriptor<2> statDesc[2];
|
||||
Descriptor &res{statDesc[0].descriptor()};
|
||||
RTNAME(AllDim)(res, *array, /*DIM=*/1, __FILE__, __LINE__);
|
||||
EXPECT_EQ(res.rank(), 1);
|
||||
EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Logical, 4}.raw()));
|
||||
|
@ -246,6 +271,22 @@ TEST(Reductions, Logical) {
|
|||
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 1);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 1);
|
||||
res.Destroy();
|
||||
RTNAME(ParityDim)(res, *array, /*DIM=*/1, __FILE__, __LINE__);
|
||||
EXPECT_EQ(res.rank(), 1);
|
||||
EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Logical, 4}.raw()));
|
||||
EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
|
||||
EXPECT_EQ(res.GetDimension(0).Extent(), 2);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 0);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 0);
|
||||
res.Destroy();
|
||||
RTNAME(ParityDim)(res, *array, /*DIM=*/2, __FILE__, __LINE__);
|
||||
EXPECT_EQ(res.rank(), 1);
|
||||
EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Logical, 4}.raw()));
|
||||
EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
|
||||
EXPECT_EQ(res.GetDimension(0).Extent(), 2);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 1);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 1);
|
||||
res.Destroy();
|
||||
RTNAME(CountDim)(res, *array, /*DIM=*/1, /*KIND=*/4, __FILE__, __LINE__);
|
||||
EXPECT_EQ(res.rank(), 1);
|
||||
EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 4}.raw()));
|
||||
|
@ -262,4 +303,123 @@ TEST(Reductions, Logical) {
|
|||
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int64_t>(0), 1);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int64_t>(1), 1);
|
||||
res.Destroy();
|
||||
bool boolValue{false};
|
||||
Descriptor &target{statDesc[1].descriptor()};
|
||||
target.Establish(TypeCategory::Logical, 1, static_cast<void *>(&boolValue), 0,
|
||||
nullptr, CFI_attribute_pointer);
|
||||
RTNAME(Findloc)
|
||||
(res, *array, target, /*KIND=*/4, __FILE__, __LINE__, nullptr,
|
||||
/*BACK=*/false);
|
||||
EXPECT_EQ(res.rank(), 1);
|
||||
EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 4}.raw()));
|
||||
EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
|
||||
EXPECT_EQ(res.GetDimension(0).Extent(), 2);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 1);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 1);
|
||||
res.Destroy();
|
||||
boolValue = true;
|
||||
RTNAME(Findloc)
|
||||
(res, *array, target, /*KIND=*/4, __FILE__, __LINE__, nullptr, /*BACK=*/true);
|
||||
EXPECT_EQ(res.rank(), 1);
|
||||
EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 4}.raw()));
|
||||
EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
|
||||
EXPECT_EQ(res.GetDimension(0).Extent(), 2);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(0), 2);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<std::int32_t>(1), 2);
|
||||
res.Destroy();
|
||||
}
|
||||
|
||||
TEST(Reductions, FindlocNumeric) {
|
||||
std::vector<int> shape{2, 3};
|
||||
auto realArray{MakeArray<TypeCategory::Real, 8>(shape,
|
||||
std::vector<double>{0.0, -0.0, 1.0, 3.14,
|
||||
std::numeric_limits<double>::quiet_NaN(),
|
||||
std::numeric_limits<double>::infinity()})};
|
||||
ASSERT_EQ(realArray->ElementBytes(), sizeof(double));
|
||||
StaticDescriptor<2> statDesc[2];
|
||||
Descriptor &res{statDesc[0].descriptor()};
|
||||
// Find the first zero
|
||||
Descriptor &target{statDesc[1].descriptor()};
|
||||
double value{0.0};
|
||||
target.Establish(TypeCategory::Real, 8, static_cast<void *>(&value), 0,
|
||||
nullptr, CFI_attribute_pointer);
|
||||
RTNAME(Findloc)
|
||||
(res, *realArray, target, 8, __FILE__, __LINE__, nullptr, /*BACK=*/false);
|
||||
EXPECT_EQ(res.rank(), 1);
|
||||
EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 8}.raw()));
|
||||
EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
|
||||
EXPECT_EQ(res.GetDimension(0).UpperBound(), 2);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(0), 1);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(1), 1);
|
||||
res.Destroy();
|
||||
// Find last zero (even though it's negative)
|
||||
RTNAME(Findloc)
|
||||
(res, *realArray, target, 8, __FILE__, __LINE__, nullptr, /*BACK=*/true);
|
||||
EXPECT_EQ(res.rank(), 1);
|
||||
EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 8}.raw()));
|
||||
EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
|
||||
EXPECT_EQ(res.GetDimension(0).UpperBound(), 2);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(0), 2);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(1), 1);
|
||||
res.Destroy();
|
||||
// Find the +Inf
|
||||
value = std::numeric_limits<double>::infinity();
|
||||
RTNAME(Findloc)
|
||||
(res, *realArray, target, 8, __FILE__, __LINE__, nullptr, /*BACK=*/false);
|
||||
EXPECT_EQ(res.rank(), 1);
|
||||
EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 8}.raw()));
|
||||
EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
|
||||
EXPECT_EQ(res.GetDimension(0).UpperBound(), 2);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(0), 2);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(1), 3);
|
||||
res.Destroy();
|
||||
// Ensure that we can't find a NaN
|
||||
value = std::numeric_limits<double>::quiet_NaN();
|
||||
RTNAME(Findloc)
|
||||
(res, *realArray, target, 8, __FILE__, __LINE__, nullptr, /*BACK=*/false);
|
||||
EXPECT_EQ(res.rank(), 1);
|
||||
EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 8}.raw()));
|
||||
EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
|
||||
EXPECT_EQ(res.GetDimension(0).UpperBound(), 2);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(0), 0);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(1), 0);
|
||||
res.Destroy();
|
||||
// Find a value of a distinct type
|
||||
int intValue{1};
|
||||
target.Establish(TypeCategory::Integer, 4, static_cast<void *>(&intValue), 0,
|
||||
nullptr, CFI_attribute_pointer);
|
||||
RTNAME(Findloc)
|
||||
(res, *realArray, target, 8, __FILE__, __LINE__, nullptr, /*BACK=*/false);
|
||||
EXPECT_EQ(res.rank(), 1);
|
||||
EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 8}.raw()));
|
||||
EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
|
||||
EXPECT_EQ(res.GetDimension(0).UpperBound(), 2);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(0), 1);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(1), 2);
|
||||
res.Destroy();
|
||||
// Partial reductions
|
||||
value = 1.0;
|
||||
target.Establish(TypeCategory::Real, 8, static_cast<void *>(&value), 0,
|
||||
nullptr, CFI_attribute_pointer);
|
||||
RTNAME(FindlocDim)
|
||||
(res, *realArray, target, 8, /*DIM=*/1, __FILE__, __LINE__, nullptr,
|
||||
/*BACK=*/false);
|
||||
EXPECT_EQ(res.rank(), 1);
|
||||
EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 8}.raw()));
|
||||
EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
|
||||
EXPECT_EQ(res.GetDimension(0).UpperBound(), 3);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(0), 0);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(1), 1);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(2), 0);
|
||||
res.Destroy();
|
||||
RTNAME(FindlocDim)
|
||||
(res, *realArray, target, 8, /*DIM=*/2, __FILE__, __LINE__, nullptr,
|
||||
/*BACK=*/true);
|
||||
EXPECT_EQ(res.rank(), 1);
|
||||
EXPECT_EQ(res.type().raw(), (TypeCode{TypeCategory::Integer, 8}.raw()));
|
||||
EXPECT_EQ(res.GetDimension(0).LowerBound(), 1);
|
||||
EXPECT_EQ(res.GetDimension(0).UpperBound(), 2);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(0), 2);
|
||||
EXPECT_EQ(*res.ZeroBasedIndexedElement<SubscriptValue>(1), 0);
|
||||
res.Destroy();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue