1 //===-- flang/unittests/Runtime/Transformational.cpp ----------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "flang/Runtime/transformational.h"
10 #include "gtest/gtest.h"
12 #include "flang/Common/float128.h"
13 #include "flang/Runtime/type-code.h"
16 using namespace Fortran::runtime
;
17 using Fortran::common::TypeCategory
;
20 using BesselFuncType
= std::function
<void(Descriptor
&, int32_t, int32_t,
21 CppTypeFor
<TypeCategory::Real
, KIND
>, CppTypeFor
<TypeCategory::Real
, KIND
>,
22 CppTypeFor
<TypeCategory::Real
, KIND
>, const char *, int)>;
25 using BesselX0FuncType
=
26 std::function
<void(Descriptor
&, int32_t, int32_t, const char *, int)>;
29 constexpr CppTypeFor
<TypeCategory::Real
, KIND
>
30 besselEpsilon
= CppTypeFor
<TypeCategory::Real
, KIND
>(1e-4);
33 static void testBesselJn(BesselFuncType
<KIND
> rtFunc
, int32_t n1
, int32_t n2
,
34 CppTypeFor
<TypeCategory::Real
, KIND
> x
,
35 const std::vector
<CppTypeFor
<TypeCategory::Real
, KIND
>> &expected
) {
36 StaticDescriptor desc
;
37 Descriptor
&result
{desc
.descriptor()};
38 unsigned len
= expected
.size();
40 CppTypeFor
<TypeCategory::Real
, KIND
> anc0
= len
> 0 ? expected
[len
- 1] : 0.0;
41 CppTypeFor
<TypeCategory::Real
, KIND
> anc1
= len
> 1 ? expected
[len
- 2] : 0.0;
43 rtFunc(result
, n1
, n2
, x
, anc0
, anc1
, __FILE__
, __LINE__
);
45 EXPECT_EQ(result
.type(), (TypeCode
{TypeCategory::Real
, KIND
}));
46 EXPECT_EQ(result
.rank(), 1);
48 result
.ElementBytes(), sizeof(CppTypeFor
<TypeCategory::Real
, KIND
>));
49 EXPECT_EQ(result
.GetDimension(0).LowerBound(), 1);
50 EXPECT_EQ(result
.GetDimension(0).Extent(), len
);
52 for (size_t j
{0}; j
< len
; ++j
) {
54 (*result
.ZeroBasedIndexedElement
<CppTypeFor
<TypeCategory::Real
, KIND
>>(
56 expected
[j
], besselEpsilon
<KIND
>);
61 static void testBesselJnX0(
62 BesselX0FuncType
<KIND
> rtFunc
, int32_t n1
, int32_t n2
) {
63 StaticDescriptor desc
;
64 Descriptor
&result
{desc
.descriptor()};
66 rtFunc(result
, n1
, n2
, __FILE__
, __LINE__
);
68 EXPECT_EQ(result
.type(), (TypeCode
{TypeCategory::Real
, KIND
}));
69 EXPECT_EQ(result
.rank(), 1);
70 EXPECT_EQ(result
.GetDimension(0).LowerBound(), 1);
71 EXPECT_EQ(result
.GetDimension(0).Extent(), n2
>= n1
? n2
- n1
+ 1 : 0);
78 (*result
.ZeroBasedIndexedElement
<CppTypeFor
<TypeCategory::Real
, KIND
>>(
80 (n1
== 0) ? 1.0 : 0.0, 1e-5);
82 for (int j
{1}; j
< (n2
- n1
+ 1); ++j
) {
84 (*result
.ZeroBasedIndexedElement
<CppTypeFor
<TypeCategory::Real
, KIND
>>(
86 0.0, besselEpsilon
<KIND
>);
90 template <int KIND
> static void testBesselJn(BesselFuncType
<KIND
> rtFunc
) {
91 testBesselJn
<KIND
>(rtFunc
, 1, 0, 1.0, {});
92 testBesselJn
<KIND
>(rtFunc
, 0, 0, 1.0, {0.765197694});
93 testBesselJn
<KIND
>(rtFunc
, 0, 1, 1.0, {0.765197694, 0.440050572});
95 rtFunc
, 0, 2, 1.0, {0.765197694, 0.440050572, 0.114903487});
96 testBesselJn
<KIND
>(rtFunc
, 1, 5, 5.0,
97 {-0.327579111, 0.046565145, 0.364831239, 0.391232371, 0.261140555});
100 template <int KIND
> static void testBesselJnX0(BesselX0FuncType
<KIND
> rtFunc
) {
101 testBesselJnX0
<KIND
>(rtFunc
, 1, 0);
102 testBesselJnX0
<KIND
>(rtFunc
, 0, 0);
103 testBesselJnX0
<KIND
>(rtFunc
, 1, 1);
104 testBesselJnX0
<KIND
>(rtFunc
, 0, 3);
105 testBesselJnX0
<KIND
>(rtFunc
, 1, 4);
108 static void testBesselJn() {
109 testBesselJn
<4>(RTNAME(BesselJn_4
));
110 testBesselJn
<8>(RTNAME(BesselJn_8
));
112 testBesselJn
<10>(RTNAME(BesselJn_10
));
114 #if HAS_LDBL128 || HAS_FLOAT128
115 testBesselJn
<16>(RTNAME(BesselJn_16
));
118 testBesselJnX0
<4>(RTNAME(BesselJnX0_4
));
119 testBesselJnX0
<8>(RTNAME(BesselJnX0_8
));
121 testBesselJnX0
<10>(RTNAME(BesselJnX0_10
));
123 #if HAS_LDBL128 || HAS_FLOAT128
124 testBesselJnX0
<16>(RTNAME(BesselJnX0_16
));
128 TEST(Transformational
, BesselJn
) { testBesselJn(); }
131 static void testBesselYn(BesselFuncType
<KIND
> rtFunc
, int32_t n1
, int32_t n2
,
132 CppTypeFor
<TypeCategory::Real
, KIND
> x
,
133 const std::vector
<CppTypeFor
<TypeCategory::Real
, KIND
>> &expected
) {
134 StaticDescriptor desc
;
135 Descriptor
&result
{desc
.descriptor()};
136 unsigned len
= expected
.size();
138 CppTypeFor
<TypeCategory::Real
, KIND
> anc0
= len
> 0 ? expected
[0] : 0.0;
139 CppTypeFor
<TypeCategory::Real
, KIND
> anc1
= len
> 1 ? expected
[1] : 0.0;
141 rtFunc(result
, n1
, n2
, x
, anc0
, anc1
, __FILE__
, __LINE__
);
143 EXPECT_EQ(result
.type(), (TypeCode
{TypeCategory::Real
, KIND
}));
144 EXPECT_EQ(result
.rank(), 1);
146 result
.ElementBytes(), sizeof(CppTypeFor
<TypeCategory::Real
, KIND
>));
147 EXPECT_EQ(result
.GetDimension(0).LowerBound(), 1);
148 EXPECT_EQ(result
.GetDimension(0).Extent(), len
);
150 for (size_t j
{0}; j
< len
; ++j
) {
152 (*result
.ZeroBasedIndexedElement
<CppTypeFor
<TypeCategory::Real
, KIND
>>(
154 expected
[j
], besselEpsilon
<KIND
>);
159 static void testBesselYnX0(
160 BesselX0FuncType
<KIND
> rtFunc
, int32_t n1
, int32_t n2
) {
161 StaticDescriptor
<2> desc
;
162 Descriptor
&result
{desc
.descriptor()};
164 rtFunc(result
, n1
, n2
, __FILE__
, __LINE__
);
166 EXPECT_EQ(result
.type(), (TypeCode
{TypeCategory::Real
, KIND
}));
167 EXPECT_EQ(result
.rank(), 1);
168 EXPECT_EQ(result
.GetDimension(0).LowerBound(), 1);
169 EXPECT_EQ(result
.GetDimension(0).Extent(), n2
>= n1
? n2
- n1
+ 1 : 0);
175 for (int j
{0}; j
< (n2
- n1
+ 1); ++j
) {
177 (*result
.ZeroBasedIndexedElement
<CppTypeFor
<TypeCategory::Real
, KIND
>>(
179 (-std::numeric_limits
<
180 CppTypeFor
<TypeCategory::Real
, KIND
>>::infinity()));
184 template <int KIND
> static void testBesselYn(BesselFuncType
<KIND
> rtFunc
) {
185 testBesselYn
<KIND
>(rtFunc
, 1, 0, 1.0, {});
186 testBesselYn
<KIND
>(rtFunc
, 0, 0, 1.0, {0.08825695});
187 testBesselYn
<KIND
>(rtFunc
, 0, 1, 1.0, {0.08825695, -0.7812128});
188 testBesselYn
<KIND
>(rtFunc
, 0, 2, 1.0, {0.0882569555, -0.7812128, -1.6506826});
189 testBesselYn
<KIND
>(rtFunc
, 1, 5, 1.0,
190 {-0.7812128, -1.6506826, -5.8215175, -33.278423, -260.40588});
193 template <int KIND
> static void testBesselYnX0(BesselX0FuncType
<KIND
> rtFunc
) {
194 testBesselYnX0
<KIND
>(rtFunc
, 1, 0);
195 testBesselYnX0
<KIND
>(rtFunc
, 0, 0);
196 testBesselYnX0
<KIND
>(rtFunc
, 1, 1);
197 testBesselYnX0
<KIND
>(rtFunc
, 0, 3);
198 testBesselYnX0
<KIND
>(rtFunc
, 1, 4);
201 static void testBesselYn() {
202 testBesselYn
<4>(RTNAME(BesselYn_4
));
203 testBesselYn
<8>(RTNAME(BesselYn_8
));
205 testBesselYn
<10>(RTNAME(BesselYn_10
));
207 #if HAS_LDBL128 || HAS_FLOAT128
208 testBesselYn
<16>(RTNAME(BesselYn_16
));
211 testBesselYnX0
<4>(RTNAME(BesselYnX0_4
));
212 testBesselYnX0
<8>(RTNAME(BesselYnX0_8
));
214 testBesselYnX0
<10>(RTNAME(BesselYnX0_10
));
216 #if HAS_LDBL128 || HAS_FLOAT128
217 testBesselYnX0
<16>(RTNAME(BesselYnX0_16
));
221 TEST(Transformational
, BesselYn
) { testBesselYn(); }
223 TEST(Transformational
, Shifts
) {
226 auto array
{MakeArray
<TypeCategory::Integer
, 4>(
227 std::vector
<int>{2, 3}, std::vector
<std::int32_t>{1, 2, 3, 4, 5, 6})};
228 array
->GetDimension(0).SetLowerBound(0); // shouldn't matter
229 array
->GetDimension(1).SetLowerBound(-1);
230 StaticDescriptor
<2, true> statDesc
;
231 Descriptor
&result
{statDesc
.descriptor()};
233 auto shift3
{MakeArray
<TypeCategory::Integer
, 8>(
234 std::vector
<int>{3}, std::vector
<std::int64_t>{1, -1, 2})};
235 RTNAME(Cshift
)(result
, *array
, *shift3
, 1, __FILE__
, __LINE__
);
236 EXPECT_EQ(result
.type(), array
->type());
237 EXPECT_EQ(result
.rank(), 2);
238 EXPECT_EQ(result
.GetDimension(0).LowerBound(), 1);
239 EXPECT_EQ(result
.GetDimension(0).Extent(), 2);
240 EXPECT_EQ(result
.GetDimension(1).LowerBound(), 1);
241 EXPECT_EQ(result
.GetDimension(1).Extent(), 3);
242 EXPECT_EQ(result
.type(), (TypeCode
{TypeCategory::Integer
, 4}));
243 static std::int32_t cshiftExpect1
[6]{2, 1, 4, 3, 5, 6};
244 for (int j
{0}; j
< 6; ++j
) {
246 *result
.ZeroBasedIndexedElement
<std::int32_t>(j
), cshiftExpect1
[j
]);
250 auto shift2
{MakeArray
<TypeCategory::Integer
, 1>(
251 std::vector
<int>{2}, std::vector
<std::int8_t>{1, -1})};
252 shift2
->GetDimension(0).SetLowerBound(-1); // shouldn't matter
253 RTNAME(Cshift
)(result
, *array
, *shift2
, 2, __FILE__
, __LINE__
);
254 EXPECT_EQ(result
.type(), array
->type());
255 EXPECT_EQ(result
.rank(), 2);
256 EXPECT_EQ(result
.GetDimension(0).LowerBound(), 1);
257 EXPECT_EQ(result
.GetDimension(0).Extent(), 2);
258 EXPECT_EQ(result
.GetDimension(1).LowerBound(), 1);
259 EXPECT_EQ(result
.GetDimension(1).Extent(), 3);
260 EXPECT_EQ(result
.type(), (TypeCode
{TypeCategory::Integer
, 4}));
261 static std::int32_t cshiftExpect2
[6]{3, 6, 5, 2, 1, 4};
262 for (int j
{0}; j
< 6; ++j
) {
264 *result
.ZeroBasedIndexedElement
<std::int32_t>(j
), cshiftExpect2
[j
]);
268 // VECTOR 1 3 5 2 4 6
269 auto vector
{MakeArray
<TypeCategory::Integer
, 4>(
270 std::vector
<int>{6}, std::vector
<std::int32_t>{1, 2, 3, 4, 5, 6})};
271 vector
->GetDimension(0).SetLowerBound(0);
272 StaticDescriptor
<1, true> vectorDesc
;
273 Descriptor
&vectorResult
{vectorDesc
.descriptor()};
275 RTNAME(CshiftVector
)(vectorResult
, *vector
, 2, __FILE__
, __LINE__
);
276 EXPECT_EQ(vectorResult
.type(), array
->type());
277 EXPECT_EQ(vectorResult
.rank(), 1);
278 EXPECT_EQ(vectorResult
.GetDimension(0).LowerBound(), 1);
279 EXPECT_EQ(vectorResult
.GetDimension(0).Extent(), 6);
280 EXPECT_EQ(vectorResult
.type(), (TypeCode
{TypeCategory::Integer
, 4}));
281 static std::int32_t cshiftExpect3
[6]{3, 4, 5, 6, 1, 2};
282 for (int j
{0}; j
< 6; ++j
) {
283 EXPECT_EQ(*vectorResult
.ZeroBasedIndexedElement
<std::int32_t>(j
),
286 vectorResult
.Destroy();
288 RTNAME(CshiftVector
)(vectorResult
, *vector
, -2, __FILE__
, __LINE__
);
289 EXPECT_EQ(vectorResult
.type(), array
->type());
290 EXPECT_EQ(vectorResult
.rank(), 1);
291 EXPECT_EQ(vectorResult
.GetDimension(0).LowerBound(), 1);
292 EXPECT_EQ(vectorResult
.GetDimension(0).Extent(), 6);
293 EXPECT_EQ(vectorResult
.type(), (TypeCode
{TypeCategory::Integer
, 4}));
294 static std::int32_t cshiftExpect4
[6]{5, 6, 1, 2, 3, 4};
295 for (int j
{0}; j
< 6; ++j
) {
296 EXPECT_EQ(*vectorResult
.ZeroBasedIndexedElement
<std::int32_t>(j
),
299 vectorResult
.Destroy();
301 // VECTOR 1 3 5 2 4 6 WITH non zero lower bound in a negative cshift.
302 auto vectorWithLowerBounds
{MakeArray
<TypeCategory::Integer
, 4>(
303 std::vector
<int>{6}, std::vector
<std::int32_t>{1, 2, 3, 4, 5, 6})};
304 vectorWithLowerBounds
->GetDimension(0).SetLowerBound(2);
307 (vectorResult
, *vectorWithLowerBounds
, -2, __FILE__
, __LINE__
);
308 EXPECT_EQ(vectorResult
.type(), array
->type());
309 EXPECT_EQ(vectorResult
.rank(), 1);
310 EXPECT_EQ(vectorResult
.GetDimension(0).LowerBound(), 1);
311 EXPECT_EQ(vectorResult
.GetDimension(0).Extent(), 6);
312 EXPECT_EQ(vectorResult
.type(), (TypeCode
{TypeCategory::Integer
, 4}));
313 static std::int32_t cshiftExpect5
[6]{5, 6, 1, 2, 3, 4};
314 for (int j
{0}; j
< 6; ++j
) {
315 EXPECT_EQ(*vectorResult
.ZeroBasedIndexedElement
<std::int32_t>(j
),
318 vectorResult
.Destroy();
320 auto boundary
{MakeArray
<TypeCategory::Integer
, 4>(
321 std::vector
<int>{3}, std::vector
<std::int32_t>{-1, -2, -3})};
322 boundary
->GetDimension(0).SetLowerBound(9); // shouldn't matter
323 RTNAME(Eoshift
)(result
, *array
, *shift3
, &*boundary
, 1, __FILE__
, __LINE__
);
324 EXPECT_EQ(result
.type(), array
->type());
325 EXPECT_EQ(result
.rank(), 2);
326 EXPECT_EQ(result
.GetDimension(0).LowerBound(), 1);
327 EXPECT_EQ(result
.GetDimension(0).Extent(), 2);
328 EXPECT_EQ(result
.GetDimension(1).LowerBound(), 1);
329 EXPECT_EQ(result
.GetDimension(1).Extent(), 3);
330 EXPECT_EQ(result
.type(), (TypeCode
{TypeCategory::Integer
, 4}));
331 static std::int32_t eoshiftExpect1
[6]{2, -1, -2, 3, -3, -3};
332 for (int j
{0}; j
< 6; ++j
) {
334 *result
.ZeroBasedIndexedElement
<std::int32_t>(j
), eoshiftExpect1
[j
]);
339 StaticDescriptor
<0> boundaryDescriptor
;
340 Descriptor vectorBoundary
{boundaryDescriptor
.descriptor()};
341 std::int32_t boundaryValue
{343};
342 vectorBoundary
.Establish(TypeCategory::Integer
, 4,
343 const_cast<void *>(reinterpret_cast<const void *>(&boundaryValue
)), 0);
344 RTNAME(EoshiftVector
)
345 (vectorResult
, *vector
, 2, &vectorBoundary
, __FILE__
, __LINE__
);
346 EXPECT_EQ(vectorResult
.type(), array
->type());
347 EXPECT_EQ(vectorResult
.rank(), 1);
348 EXPECT_EQ(vectorResult
.GetDimension(0).LowerBound(), 1);
349 EXPECT_EQ(vectorResult
.GetDimension(0).Extent(), 6);
350 EXPECT_EQ(vectorResult
.type(), (TypeCode
{TypeCategory::Integer
, 4}));
351 static std::int32_t eoshiftVectorExpect
[6]{3, 4, 5, 6, 343, 343};
352 for (int j
{0}; j
< 6; ++j
) {
353 EXPECT_EQ(*vectorResult
.ZeroBasedIndexedElement
<std::int32_t>(j
),
354 eoshiftVectorExpect
[j
]);
356 vectorResult
.Destroy();
358 // VECTOR EOSHIFT on input with non zero lower bounds
359 RTNAME(EoshiftVector
)
360 (vectorResult
, *vectorWithLowerBounds
, -2, &vectorBoundary
, __FILE__
,
362 EXPECT_EQ(vectorResult
.type(), array
->type());
363 EXPECT_EQ(vectorResult
.rank(), 1);
364 EXPECT_EQ(vectorResult
.GetDimension(0).LowerBound(), 1);
365 EXPECT_EQ(vectorResult
.GetDimension(0).Extent(), 6);
366 EXPECT_EQ(vectorResult
.type(), (TypeCode
{TypeCategory::Integer
, 4}));
367 static std::int32_t eoshiftVectorExpect2
[6]{343, 343, 1, 2, 3, 4};
368 for (int j
{0}; j
< 6; ++j
) {
369 EXPECT_EQ(*vectorResult
.ZeroBasedIndexedElement
<std::int32_t>(j
),
370 eoshiftVectorExpect2
[j
]);
372 vectorResult
.Destroy();
375 TEST(Transformational
, Pack
) {
378 auto array
{MakeArray
<TypeCategory::Integer
, 4>(
379 std::vector
<int>{2, 3}, std::vector
<std::int32_t>{1, 2, 3, 4, 5, 6})};
380 array
->GetDimension(0).SetLowerBound(2); // shouldn't matter
381 array
->GetDimension(1).SetLowerBound(-1);
382 auto mask
{MakeArray
<TypeCategory::Logical
, 1>(std::vector
<int>{2, 3},
383 std::vector
<std::uint8_t>{false, true, true, false, false, true})};
384 mask
->GetDimension(0).SetLowerBound(0); // shouldn't matter
385 mask
->GetDimension(1).SetLowerBound(2);
386 StaticDescriptor
<maxRank
, true> statDesc
;
387 Descriptor
&result
{statDesc
.descriptor()};
389 RTNAME(Pack
)(result
, *array
, *mask
, nullptr, __FILE__
, __LINE__
);
390 EXPECT_EQ(result
.type(), array
->type());
391 EXPECT_EQ(result
.rank(), 1);
392 EXPECT_EQ(result
.GetDimension(0).LowerBound(), 1);
393 EXPECT_EQ(result
.GetDimension(0).Extent(), 3);
394 static std::int32_t packExpect1
[3]{2, 3, 6};
395 for (int j
{0}; j
< 3; ++j
) {
396 EXPECT_EQ(*result
.ZeroBasedIndexedElement
<std::int32_t>(j
), packExpect1
[j
])
401 auto vector
{MakeArray
<TypeCategory::Integer
, 4>(
402 std::vector
<int>{5}, std::vector
<std::int32_t>{-1, -2, -3, -4, -5})};
403 RTNAME(Pack
)(result
, *array
, *mask
, &*vector
, __FILE__
, __LINE__
);
404 EXPECT_EQ(result
.type(), array
->type());
405 EXPECT_EQ(result
.rank(), 1);
406 EXPECT_EQ(result
.GetDimension(0).LowerBound(), 1);
407 EXPECT_EQ(result
.GetDimension(0).Extent(), 5);
408 static std::int32_t packExpect2
[5]{2, 3, 6, -4, -5};
409 for (int j
{0}; j
< 5; ++j
) {
410 EXPECT_EQ(*result
.ZeroBasedIndexedElement
<std::int32_t>(j
), packExpect2
[j
])
416 TEST(Transformational
, Spread
) {
417 auto array
{MakeArray
<TypeCategory::Integer
, 4>(
418 std::vector
<int>{3}, std::vector
<std::int32_t>{1, 2, 3})};
419 array
->GetDimension(0).SetLowerBound(2); // shouldn't matter
420 StaticDescriptor
<2, true> statDesc
;
421 Descriptor
&result
{statDesc
.descriptor()};
423 RTNAME(Spread
)(result
, *array
, 1, 2, __FILE__
, __LINE__
);
424 EXPECT_EQ(result
.type(), array
->type());
425 EXPECT_EQ(result
.rank(), 2);
426 EXPECT_EQ(result
.GetDimension(0).LowerBound(), 1);
427 EXPECT_EQ(result
.GetDimension(0).Extent(), 2);
428 EXPECT_EQ(result
.GetDimension(1).LowerBound(), 1);
429 EXPECT_EQ(result
.GetDimension(1).Extent(), 3);
430 for (int j
{0}; j
< 6; ++j
) {
431 EXPECT_EQ(*result
.ZeroBasedIndexedElement
<std::int32_t>(j
), 1 + j
/ 2);
435 RTNAME(Spread
)(result
, *array
, 2, 2, __FILE__
, __LINE__
);
436 EXPECT_EQ(result
.type(), array
->type());
437 EXPECT_EQ(result
.rank(), 2);
438 EXPECT_EQ(result
.GetDimension(0).LowerBound(), 1);
439 EXPECT_EQ(result
.GetDimension(0).Extent(), 3);
440 EXPECT_EQ(result
.GetDimension(1).LowerBound(), 1);
441 EXPECT_EQ(result
.GetDimension(1).Extent(), 2);
442 for (int j
{0}; j
< 6; ++j
) {
443 EXPECT_EQ(*result
.ZeroBasedIndexedElement
<std::int32_t>(j
), 1 + j
% 3);
447 auto scalar
{MakeArray
<TypeCategory::Integer
, 4>(
448 std::vector
<int>{}, std::vector
<std::int32_t>{1})};
449 RTNAME(Spread
)(result
, *scalar
, 1, 2, __FILE__
, __LINE__
);
450 EXPECT_EQ(result
.type(), array
->type());
451 EXPECT_EQ(result
.rank(), 1);
452 EXPECT_EQ(result
.GetDimension(0).LowerBound(), 1);
453 EXPECT_EQ(result
.GetDimension(0).Extent(), 2);
454 for (int j
{0}; j
< 2; ++j
) {
455 EXPECT_EQ(*result
.ZeroBasedIndexedElement
<std::int32_t>(j
), 1);
460 TEST(Transformational
, Transpose
) {
463 auto array
{MakeArray
<TypeCategory::Integer
, 4>(
464 std::vector
<int>{2, 3}, std::vector
<std::int32_t>{1, 2, 3, 4, 5, 6})};
465 array
->GetDimension(0).SetLowerBound(2); // shouldn't matter
466 array
->GetDimension(1).SetLowerBound(-6);
467 StaticDescriptor
<2, true> statDesc
;
468 Descriptor
&result
{statDesc
.descriptor()};
469 RTNAME(Transpose
)(result
, *array
, __FILE__
, __LINE__
);
470 EXPECT_EQ(result
.type(), array
->type());
471 EXPECT_EQ(result
.rank(), 2);
472 EXPECT_EQ(result
.GetDimension(0).LowerBound(), 1);
473 EXPECT_EQ(result
.GetDimension(0).Extent(), 3);
474 EXPECT_EQ(result
.GetDimension(1).LowerBound(), 1);
475 EXPECT_EQ(result
.GetDimension(1).Extent(), 2);
476 static std::int32_t expect
[6]{1, 3, 5, 2, 4, 6};
477 for (int j
{0}; j
< 6; ++j
) {
478 EXPECT_EQ(*result
.ZeroBasedIndexedElement
<std::int32_t>(j
), expect
[j
]);
483 TEST(Transformational
, Unpack
) {
484 auto vector
{MakeArray
<TypeCategory::Integer
, 4>(
485 std::vector
<int>{4}, std::vector
<std::int32_t>{1, 2, 3, 4})};
486 vector
->GetDimension(0).SetLowerBound(2); // shouldn't matter
487 auto mask
{MakeArray
<TypeCategory::Logical
, 1>(std::vector
<int>{2, 3},
488 std::vector
<std::uint8_t>{false, true, true, false, false, true})};
489 mask
->GetDimension(0).SetLowerBound(0); // shouldn't matter
490 mask
->GetDimension(1).SetLowerBound(2);
491 auto field
{MakeArray
<TypeCategory::Integer
, 4>(std::vector
<int>{2, 3},
492 std::vector
<std::int32_t>{-1, -2, -3, -4, -5, -6})};
493 field
->GetDimension(0).SetLowerBound(-1); // shouldn't matter
494 StaticDescriptor
<2, true> statDesc
;
495 Descriptor
&result
{statDesc
.descriptor()};
496 RTNAME(Unpack
)(result
, *vector
, *mask
, *field
, __FILE__
, __LINE__
);
497 EXPECT_EQ(result
.type(), vector
->type());
498 EXPECT_EQ(result
.rank(), 2);
499 EXPECT_EQ(result
.GetDimension(0).LowerBound(), 1);
500 EXPECT_EQ(result
.GetDimension(0).Extent(), 2);
501 EXPECT_EQ(result
.GetDimension(1).LowerBound(), 1);
502 EXPECT_EQ(result
.GetDimension(1).Extent(), 3);
503 static std::int32_t expect
[6]{-1, 1, 2, -4, -5, 3};
504 for (int j
{0}; j
< 6; ++j
) {
505 EXPECT_EQ(*result
.ZeroBasedIndexedElement
<std::int32_t>(j
), expect
[j
]);
509 // Test for scalar value of the "field" argument
510 auto scalarField
{MakeArray
<TypeCategory::Integer
, 4>(
511 std::vector
<int>{}, std::vector
<std::int32_t>{343})};
512 RTNAME(Unpack
)(result
, *vector
, *mask
, *scalarField
, __FILE__
, __LINE__
);
513 EXPECT_EQ(result
.rank(), 2);
514 EXPECT_EQ(result
.GetDimension(0).LowerBound(), 1);
515 EXPECT_EQ(result
.GetDimension(0).Extent(), 2);
516 EXPECT_EQ(result
.GetDimension(1).LowerBound(), 1);
517 EXPECT_EQ(result
.GetDimension(1).Extent(), 3);
518 static std::int32_t scalarExpect
[6]{343, 1, 2, 343, 343, 3};
519 for (int j
{0}; j
< 6; ++j
) {
521 *result
.ZeroBasedIndexedElement
<std::int32_t>(j
), scalarExpect
[j
]);
527 // Make sure the destination descriptor is created by the runtime
528 // with proper element size, when REAL*10 maps to 'long double'.
529 #define Real10CppType long double
530 TEST(Transformational
, TransposeReal10
) {
533 auto array
{MakeArray
<TypeCategory::Real
, 10>(std::vector
<int>{2, 3},
534 std::vector
<Real10CppType
>{1.0, 2.0, 3.0, 4.0, 5.0, 6.0},
535 sizeof(Real10CppType
))};
536 StaticDescriptor
<2, true> statDesc
;
537 Descriptor
&result
{statDesc
.descriptor()};
538 RTNAME(Transpose
)(result
, *array
, __FILE__
, __LINE__
);
539 EXPECT_EQ(result
.ElementBytes(), sizeof(Real10CppType
));
540 EXPECT_EQ(result
.type(), array
->type());
541 EXPECT_EQ(result
.rank(), 2);
542 EXPECT_EQ(result
.GetDimension(0).LowerBound(), 1);
543 EXPECT_EQ(result
.GetDimension(0).Extent(), 3);
544 EXPECT_EQ(result
.GetDimension(1).LowerBound(), 1);
545 EXPECT_EQ(result
.GetDimension(1).Extent(), 2);
546 static Real10CppType expect
[6]{1.0, 3.0, 5.0, 2.0, 4.0, 6.0};
547 for (int j
{0}; j
< 6; ++j
) {
548 EXPECT_EQ(*result
.ZeroBasedIndexedElement
<Real10CppType
>(j
), expect
[j
]);