133 lines · cpp
1#define AVOID_NATIVE_UINT128_T 12#include "flang/Common/uint128.h"3#include "flang/Testing/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 19#else10#undef HAS_NATIVE_UINT128_T11#endif12 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_T53static __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(m, n);99 TestVsNative(~m, n);100 TestVsNative(m, ~n);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 conversion110 Test(~m, 10000000000000000);111 }112 }113}114#endif115 116int main() {117 for (std::uint64_t j{0}; j < 64; ++j) {118 Test(j);119 Test(~j);120 Test(std::uint64_t(1) << j);121 for (std::uint64_t k{0}; k < 64; ++k) {122 Test(j, k);123 }124 }125#if HAS_NATIVE_UINT128_T126 llvm::outs() << "Environment has native __uint128_t\n";127 TestVsNative();128#else129 llvm::outs() << "Environment lacks native __uint128_t\n";130#endif131 return testing::Complete();132}133