1 #define AVOID_NATIVE_UINT128_T 1
2 #include "flang/Common/uint128.h"
4 #include "llvm/Support/raw_ostream.h"
7 #if (defined __GNUC__ || defined __clang__) && defined __SIZEOF_INT128__
8 #define HAS_NATIVE_UINT128_T 1
10 #undef HAS_NATIVE_UINT128_T
13 using U128
= Fortran::common::UnsignedInt128
;
15 static void Test(std::uint64_t 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
));
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
);
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));
37 static void Test(std::uint64_t x
, std::uint64_t 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
));
48 MATCH(x
/ y
, static_cast<std::uint64_t>(m
/ n
));
52 #if HAS_NATIVE_UINT128_T
53 static __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
);
58 static U128
FromNative(__uint128_t n
) {
59 return U128
{static_cast<std::uint64_t>(n
>> 64)} << 64 |
60 U128
{static_cast<std::uint64_t>(n
)};
63 static 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
));
80 TEST(ToNative(m
<< n
) == (x
<< y
));
81 TEST(ToNative(m
>> n
) == (x
>> y
));
83 TEST(ToNative(m
+ n
) == (x
+ y
));
84 TEST(ToNative(m
- n
) == (x
- y
));
85 TEST(ToNative(m
* n
) == (x
* y
));
87 TEST(ToNative(m
/ n
) == (x
/ y
));
88 TEST(ToNative(m
% n
) == (x
% y
));
89 TEST(ToNative(m
- n
* (m
/ n
)) == (x
% y
));
93 static 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};
101 TestVsNative(~m
, ~n
);
102 TestVsNative(m
^ n
, n
);
103 TestVsNative(m
, m
^ n
);
104 TestVsNative(m
^ ~n
, n
);
105 TestVsNative(m
, ~m
^ n
);
106 TestVsNative(m
^ ~n
, m
^ n
);
107 TestVsNative(m
^ n
, ~m
^ n
);
108 TestVsNative(m
^ ~n
, ~m
^ n
);
109 Test(m
, 10000000000000000); // important case for decimal conversion
110 Test(~m
, 10000000000000000);
117 for (std::uint64_t j
{0}; j
< 64; ++j
) {
120 Test(std::uint64_t(1) << j
);
121 for (std::uint64_t k
{0}; k
< 64; ++k
) {
125 #if HAS_NATIVE_UINT128_T
126 llvm::outs() << "Environment has native __uint128_t\n";
129 llvm::outs() << "Environment lacks native __uint128_t\n";
131 return testing::Complete();