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/Runtime/type-code.h"
15 using namespace Fortran::runtime
;
16 using Fortran::common::TypeCategory
;
19 using BesselFuncType
= std::function
<void(Descriptor
&, int32_t, int32_t,
20 CppTypeFor
<TypeCategory::Real
, KIND
>, CppTypeFor
<TypeCategory::Real
, KIND
>,
21 CppTypeFor
<TypeCategory::Real
, KIND
>, const char *, int)>;
24 using BesselX0FuncType
=
25 std::function
<void(Descriptor
&, int32_t, int32_t, const char *, int)>;
28 constexpr CppTypeFor
<TypeCategory::Real
, KIND
>
29 besselEpsilon
= CppTypeFor
<TypeCategory::Real
, KIND
>(1e-4);
32 static void testBesselJn(BesselFuncType
<KIND
> rtFunc
, int32_t n1
, int32_t n2
,
33 CppTypeFor
<TypeCategory::Real
, KIND
> x
,
34 const std::vector
<CppTypeFor
<TypeCategory::Real
, KIND
>> &expected
) {
35 StaticDescriptor
<1> desc
;
36 Descriptor
&result
{desc
.descriptor()};
37 unsigned len
= expected
.size();
39 CppTypeFor
<TypeCategory::Real
, KIND
> anc0
= len
> 0 ? expected
[len
- 1] : 0.0;
40 CppTypeFor
<TypeCategory::Real
, KIND
> anc1
= len
> 1 ? expected
[len
- 2] : 0.0;
42 rtFunc(result
, n1
, n2
, x
, anc0
, anc1
, __FILE__
, __LINE__
);
44 EXPECT_EQ(result
.type(), (TypeCode
{TypeCategory::Real
, KIND
}));
45 EXPECT_EQ(result
.rank(), 1);
47 result
.ElementBytes(), sizeof(CppTypeFor
<TypeCategory::Real
, KIND
>));
48 EXPECT_EQ(result
.GetDimension(0).LowerBound(), 1);
49 EXPECT_EQ(result
.GetDimension(0).Extent(), len
);
51 for (size_t j
{0}; j
< len
; ++j
) {
53 (*result
.ZeroBasedIndexedElement
<CppTypeFor
<TypeCategory::Real
, KIND
>>(
55 expected
[j
], besselEpsilon
<KIND
>);
60 static void testBesselJnX0(
61 BesselX0FuncType
<KIND
> rtFunc
, int32_t n1
, int32_t n2
) {
62 StaticDescriptor
<1> desc
;
63 Descriptor
&result
{desc
.descriptor()};
65 rtFunc(result
, n1
, n2
, __FILE__
, __LINE__
);
67 EXPECT_EQ(result
.type(), (TypeCode
{TypeCategory::Real
, KIND
}));
68 EXPECT_EQ(result
.rank(), 1);
69 EXPECT_EQ(result
.GetDimension(0).LowerBound(), 1);
70 EXPECT_EQ(result
.GetDimension(0).Extent(), n2
>= n1
? n2
- n1
+ 1 : 0);
77 (*result
.ZeroBasedIndexedElement
<CppTypeFor
<TypeCategory::Real
, KIND
>>(
79 (n1
== 0) ? 1.0 : 0.0, 1e-5);
81 for (int j
{1}; j
< (n2
- n1
+ 1); ++j
) {
83 (*result
.ZeroBasedIndexedElement
<CppTypeFor
<TypeCategory::Real
, KIND
>>(
85 0.0, besselEpsilon
<KIND
>);
89 template <int KIND
> static void testBesselJn(BesselFuncType
<KIND
> rtFunc
) {
90 testBesselJn
<KIND
>(rtFunc
, 1, 0, 1.0, {});
91 testBesselJn
<KIND
>(rtFunc
, 0, 0, 1.0, {0.765197694});
92 testBesselJn
<KIND
>(rtFunc
, 0, 1, 1.0, {0.765197694, 0.440050572});
94 rtFunc
, 0, 2, 1.0, {0.765197694, 0.440050572, 0.114903487});
95 testBesselJn
<KIND
>(rtFunc
, 1, 5, 5.0,
96 {-0.327579111, 0.046565145, 0.364831239, 0.391232371, 0.261140555});
99 template <int KIND
> static void testBesselJnX0(BesselX0FuncType
<KIND
> rtFunc
) {
100 testBesselJnX0
<KIND
>(rtFunc
, 1, 0);
101 testBesselJnX0
<KIND
>(rtFunc
, 0, 0);
102 testBesselJnX0
<KIND
>(rtFunc
, 1, 1);
103 testBesselJnX0
<KIND
>(rtFunc
, 0, 3);
104 testBesselJnX0
<KIND
>(rtFunc
, 1, 4);
107 static void testBesselJn() {
108 testBesselJn
<4>(RTNAME(BesselJn_4
));
109 testBesselJn
<8>(RTNAME(BesselJn_8
));
110 #if LDBL_MANT_DIG == 64
111 testBesselJn
<10>(RTNAME(BesselJn_10
));
113 #if LDBL_MANT_DIG == 113 || HAS_FLOAT128
114 testBesselJn
<16>(RTNAME(BesselJn_16
));
117 testBesselJnX0
<4>(RTNAME(BesselJnX0_4
));
118 testBesselJnX0
<8>(RTNAME(BesselJnX0_8
));
119 #if LDBL_MANT_DIG == 64
120 testBesselJnX0
<10>(RTNAME(BesselJnX0_10
));
122 #if LDBL_MANT_DIG == 113 || HAS_FLOAT128
123 testBesselJnX0
<16>(RTNAME(BesselJnX0_16
));
127 TEST(Transformational
, BesselJn
) { testBesselJn(); }
130 static void testBesselYn(BesselFuncType
<KIND
> rtFunc
, int32_t n1
, int32_t n2
,
131 CppTypeFor
<TypeCategory::Real
, KIND
> x
,
132 const std::vector
<CppTypeFor
<TypeCategory::Real
, KIND
>> &expected
) {
133 StaticDescriptor
<1> desc
;
134 Descriptor
&result
{desc
.descriptor()};
135 unsigned len
= expected
.size();
137 CppTypeFor
<TypeCategory::Real
, KIND
> anc0
= len
> 0 ? expected
[0] : 0.0;
138 CppTypeFor
<TypeCategory::Real
, KIND
> anc1
= len
> 1 ? expected
[1] : 0.0;
140 rtFunc(result
, n1
, n2
, x
, anc0
, anc1
, __FILE__
, __LINE__
);
142 EXPECT_EQ(result
.type(), (TypeCode
{TypeCategory::Real
, KIND
}));
143 EXPECT_EQ(result
.rank(), 1);
145 result
.ElementBytes(), sizeof(CppTypeFor
<TypeCategory::Real
, KIND
>));
146 EXPECT_EQ(result
.GetDimension(0).LowerBound(), 1);
147 EXPECT_EQ(result
.GetDimension(0).Extent(), len
);
149 for (size_t j
{0}; j
< len
; ++j
) {
151 (*result
.ZeroBasedIndexedElement
<CppTypeFor
<TypeCategory::Real
, KIND
>>(
153 expected
[j
], besselEpsilon
<KIND
>);
158 static void testBesselYnX0(
159 BesselX0FuncType
<KIND
> rtFunc
, int32_t n1
, int32_t n2
) {
160 StaticDescriptor
<1> desc
;
161 Descriptor
&result
{desc
.descriptor()};
163 rtFunc(result
, n1
, n2
, __FILE__
, __LINE__
);
165 EXPECT_EQ(result
.type(), (TypeCode
{TypeCategory::Real
, KIND
}));
166 EXPECT_EQ(result
.rank(), 1);
167 EXPECT_EQ(result
.GetDimension(0).LowerBound(), 1);
168 EXPECT_EQ(result
.GetDimension(0).Extent(), n2
>= n1
? n2
- n1
+ 1 : 0);
174 for (int j
{0}; j
< (n2
- n1
+ 1); ++j
) {
176 (*result
.ZeroBasedIndexedElement
<CppTypeFor
<TypeCategory::Real
, KIND
>>(
178 (-std::numeric_limits
<
179 CppTypeFor
<TypeCategory::Real
, KIND
>>::infinity()));
183 template <int KIND
> static void testBesselYn(BesselFuncType
<KIND
> rtFunc
) {
184 testBesselYn
<KIND
>(rtFunc
, 1, 0, 1.0, {});
185 testBesselYn
<KIND
>(rtFunc
, 0, 0, 1.0, {0.08825695});
186 testBesselYn
<KIND
>(rtFunc
, 0, 1, 1.0, {0.08825695, -0.7812128});
187 testBesselYn
<KIND
>(rtFunc
, 0, 2, 1.0, {0.0882569555, -0.7812128, -1.6506826});
188 testBesselYn
<KIND
>(rtFunc
, 1, 5, 1.0,
189 {-0.7812128, -1.6506826, -5.8215175, -33.278423, -260.40588});
192 template <int KIND
> static void testBesselYnX0(BesselX0FuncType
<KIND
> rtFunc
) {
193 testBesselYnX0
<KIND
>(rtFunc
, 1, 0);
194 testBesselYnX0
<KIND
>(rtFunc
, 0, 0);
195 testBesselYnX0
<KIND
>(rtFunc
, 1, 1);
196 testBesselYnX0
<KIND
>(rtFunc
, 0, 3);
197 testBesselYnX0
<KIND
>(rtFunc
, 1, 4);
200 static void testBesselYn() {
201 testBesselYn
<4>(RTNAME(BesselYn_4
));
202 testBesselYn
<8>(RTNAME(BesselYn_8
));
203 #if LDBL_MANT_DIG == 64
204 testBesselYn
<10>(RTNAME(BesselYn_10
));
206 #if LDBL_MANT_DIG == 113 || HAS_FLOAT128
207 testBesselYn
<16>(RTNAME(BesselYn_16
));
210 testBesselYnX0
<4>(RTNAME(BesselYnX0_4
));
211 testBesselYnX0
<8>(RTNAME(BesselYnX0_8
));
212 #if LDBL_MANT_DIG == 64
213 testBesselYnX0
<10>(RTNAME(BesselYnX0_10
));
215 #if LDBL_MANT_DIG == 113 || HAS_FLOAT128
216 testBesselYnX0
<16>(RTNAME(BesselYnX0_16
));
220 TEST(Transformational
, BesselYn
) { testBesselYn(); }
222 TEST(Transformational
, Shifts
) {
225 auto array
{MakeArray
<TypeCategory::Integer
, 4>(
226 std::vector
<int>{2, 3}, std::vector
<std::int32_t>{1, 2, 3, 4, 5, 6})};
227 array
->GetDimension(0).SetLowerBound(0); // shouldn't matter
228 array
->GetDimension(1).SetLowerBound(-1);
229 StaticDescriptor
<2, true> statDesc
;
230 Descriptor
&result
{statDesc
.descriptor()};
232 auto shift3
{MakeArray
<TypeCategory::Integer
, 8>(
233 std::vector
<int>{3}, std::vector
<std::int64_t>{1, -1, 2})};
234 RTNAME(Cshift
)(result
, *array
, *shift3
, 1, __FILE__
, __LINE__
);
235 EXPECT_EQ(result
.type(), array
->type());
236 EXPECT_EQ(result
.rank(), 2);
237 EXPECT_EQ(result
.GetDimension(0).LowerBound(), 1);
238 EXPECT_EQ(result
.GetDimension(0).Extent(), 2);
239 EXPECT_EQ(result
.GetDimension(1).LowerBound(), 1);
240 EXPECT_EQ(result
.GetDimension(1).Extent(), 3);
241 EXPECT_EQ(result
.type(), (TypeCode
{TypeCategory::Integer
, 4}));
242 static std::int32_t cshiftExpect1
[6]{2, 1, 4, 3, 5, 6};
243 for (int j
{0}; j
< 6; ++j
) {
245 *result
.ZeroBasedIndexedElement
<std::int32_t>(j
), cshiftExpect1
[j
]);
249 auto shift2
{MakeArray
<TypeCategory::Integer
, 1>(
250 std::vector
<int>{2}, std::vector
<std::int8_t>{1, -1})};
251 shift2
->GetDimension(0).SetLowerBound(-1); // shouldn't matter
252 shift2
->GetDimension(1).SetLowerBound(2);
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
<1, 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
]);
526 #if LDBL_MANT_DIG == 64
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
]);