1#define AVOID_NATIVE_UINT128_T 1
2#include "flang/Common/uint128.h"
3#include "testing.h"
4#include "llvm/Support/raw_ostream.h"
5#include <cinttypes>
6
7#if (defined __GNUC__ || defined __clang__) && defined __SIZEOF_INT128__
8#define HAS_NATIVE_UINT128_T 1
9#else
10#undef HAS_NATIVE_UINT128_T
11#endif
12
13using U128 = Fortran::common::UnsignedInt128;
14
15static void Test(std::uint64_t x) {
16 U128 n{x};
17 MATCH(x, static_cast<std::uint64_t>(n));
18 MATCH(~x, static_cast<std::uint64_t>(~n));
19 MATCH(-x, static_cast<std::uint64_t>(-n));
20 MATCH(!x, static_cast<std::uint64_t>(!n));
21 TEST(n == n);
22 TEST(n + n == n * static_cast<U128>(2));
23 TEST(n - n == static_cast<U128>(0));
24 TEST(n + n == n << static_cast<U128>(1));
25 TEST(n + n == n << static_cast<U128>(1));
26 TEST((n + n) - n == n);
27 TEST(((n + n) >> static_cast<U128>(1)) == n);
28 if (x != 0) {
29 TEST(static_cast<U128>(0) / n == static_cast<U128>(0));
30 TEST(static_cast<U128>(n - 1) / n == static_cast<U128>(0));
31 TEST(static_cast<U128>(n) / n == static_cast<U128>(1));
32 TEST(static_cast<U128>(n + n - 1) / n == static_cast<U128>(1));
33 TEST(static_cast<U128>(n + n) / n == static_cast<U128>(2));
34 }
35}
36
37static void Test(std::uint64_t x, std::uint64_t y) {
38 U128 m{x}, n{y};
39 MATCH(x, static_cast<std::uint64_t>(m));
40 MATCH(y, static_cast<std::uint64_t>(n));
41 MATCH(x & y, static_cast<std::uint64_t>(m & n));
42 MATCH(x | y, static_cast<std::uint64_t>(m | n));
43 MATCH(x ^ y, static_cast<std::uint64_t>(m ^ n));
44 MATCH(x + y, static_cast<std::uint64_t>(m + n));
45 MATCH(x - y, static_cast<std::uint64_t>(m - n));
46 MATCH(x * y, static_cast<std::uint64_t>(m * n));
47 if (n != 0) {
48 MATCH(x / y, static_cast<std::uint64_t>(m / n));
49 }
50}
51
52#if HAS_NATIVE_UINT128_T
53static __uint128_t ToNative(U128 n) {
54 return static_cast<__uint128_t>(static_cast<std::uint64_t>(n >> 64)) << 64 |
55 static_cast<std::uint64_t>(n);
56}
57
58static U128 FromNative(__uint128_t n) {
59 return U128{static_cast<std::uint64_t>(n >> 64)} << 64 |
60 U128{static_cast<std::uint64_t>(n)};
61}
62
63static void TestVsNative(__uint128_t x, __uint128_t y) {
64 U128 m{FromNative(x)}, n{FromNative(y)};
65 TEST(ToNative(m) == x);
66 TEST(ToNative(n) == y);
67 TEST(ToNative(~m) == ~x);
68 TEST(ToNative(-m) == -x);
69 TEST(ToNative(!m) == !x);
70 TEST(ToNative(m < n) == (x < y));
71 TEST(ToNative(m <= n) == (x <= y));
72 TEST(ToNative(m == n) == (x == y));
73 TEST(ToNative(m != n) == (x != y));
74 TEST(ToNative(m >= n) == (x >= y));
75 TEST(ToNative(m > n) == (x > y));
76 TEST(ToNative(m & n) == (x & y));
77 TEST(ToNative(m | n) == (x | y));
78 TEST(ToNative(m ^ n) == (x ^ y));
79 if (y < 128) {
80 TEST(ToNative(m << n) == (x << y));
81 TEST(ToNative(m >> n) == (x >> y));
82 }
83 TEST(ToNative(m + n) == (x + y));
84 TEST(ToNative(m - n) == (x - y));
85 TEST(ToNative(m * n) == (x * y));
86 if (y > 0) {
87 TEST(ToNative(m / n) == (x / y));
88 TEST(ToNative(m % n) == (x % y));
89 TEST(ToNative(m - n * (m / n)) == (x % y));
90 }
91}
92
93static void TestVsNative() {
94 for (int j{0}; j < 128; ++j) {
95 for (int k{0}; k < 128; ++k) {
96 __uint128_t m{1}, n{1};
97 m <<= j, n <<= k;
98 TestVsNative(x: m, y: n);
99 TestVsNative(x: ~m, y: n);
100 TestVsNative(x: m, y: ~n);
101 TestVsNative(x: ~m, y: ~n);
102 TestVsNative(x: m ^ n, y: n);
103 TestVsNative(x: m, y: m ^ n);
104 TestVsNative(x: m ^ ~n, y: n);
105 TestVsNative(x: m, y: ~m ^ n);
106 TestVsNative(x: m ^ ~n, y: m ^ n);
107 TestVsNative(x: m ^ n, y: ~m ^ n);
108 TestVsNative(x: m ^ ~n, y: ~m ^ n);
109 Test(x: m, y: 10000000000000000); // important case for decimal conversion
110 Test(x: ~m, y: 10000000000000000);
111 }
112 }
113}
114#endif
115
116int main() {
117 for (std::uint64_t j{0}; j < 64; ++j) {
118 Test(x: j);
119 Test(x: ~j);
120 Test(x: std::uint64_t(1) << j);
121 for (std::uint64_t k{0}; k < 64; ++k) {
122 Test(x: j, y: k);
123 }
124 }
125#if HAS_NATIVE_UINT128_T
126 llvm::outs() << "Environment has native __uint128_t\n";
127 TestVsNative();
128#else
129 llvm::outs() << "Environment lacks native __uint128_t\n";
130#endif
131 return testing::Complete();
132}
133

source code of flang/unittests/Evaluate/uint128.cpp