51 changes: 26 additions & 25 deletions libc/src/__support/str_to_float.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define LIBC_SRC_SUPPORT_STR_TO_FLOAT_H

#include "src/__support/CPP/Limits.h"
#include "src/__support/CPP/UInt128.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/builtin_wrappers.h"
#include "src/__support/ctype_utils.h"
Expand Down Expand Up @@ -58,11 +59,11 @@ template <> uint32_t inline leading_zeroes<uint64_t>(uint64_t inputNumber) {
return inputNumber == 0 ? 64 : fputil::clz(inputNumber);
}

static inline uint64_t low64(__uint128_t num) {
static inline uint64_t low64(const UInt128 &num) {
return static_cast<uint64_t>(num & 0xffffffffffffffff);
}

static inline uint64_t high64(__uint128_t num) {
static inline uint64_t high64(const UInt128 &num) {
return static_cast<uint64_t>(num >> 64);
}

Expand Down Expand Up @@ -116,11 +117,11 @@ eisel_lemire(typename fputil::FPBits<T>::UIntType mantissa, int32_t exp10,
const uint64_t *power_of_ten =
DETAILED_POWERS_OF_TEN[exp10 - DETAILED_POWERS_OF_TEN_MIN_EXP_10];

__uint128_t first_approx = static_cast<__uint128_t>(mantissa) *
static_cast<__uint128_t>(power_of_ten[1]);
UInt128 first_approx =
static_cast<UInt128>(mantissa) * static_cast<UInt128>(power_of_ten[1]);

// Wider Approximation
__uint128_t final_approx;
UInt128 final_approx;
// The halfway constant is used to check if the bits that will be shifted away
// intially are all 1. For doubles this is 64 (bitstype size) - 52 (final
// mantissa size) - 3 (we shift away the last two bits separately for
Expand All @@ -132,10 +133,10 @@ eisel_lemire(typename fputil::FPBits<T>::UIntType mantissa, int32_t exp10,
1;
if ((high64(first_approx) & halfway_constant) == halfway_constant &&
low64(first_approx) + mantissa < mantissa) {
__uint128_t low_bits = static_cast<__uint128_t>(mantissa) *
static_cast<__uint128_t>(power_of_ten[0]);
__uint128_t second_approx =
first_approx + static_cast<__uint128_t>(high64(low_bits));
UInt128 low_bits =
static_cast<UInt128>(mantissa) * static_cast<UInt128>(power_of_ten[0]);
UInt128 second_approx =
first_approx + static_cast<UInt128>(high64(low_bits));

if ((high64(second_approx) & halfway_constant) == halfway_constant &&
low64(second_approx) + 1 == 0 &&
Expand Down Expand Up @@ -220,31 +221,31 @@ inline bool eisel_lemire<long double>(
// full 128 bits of the power of ten to get an approximation with the same
// number of significant bits. This means that we only get the one
// approximation, and that approximation is 256 bits long.
__uint128_t approx_upper = static_cast<__uint128_t>(high64(mantissa)) *
static_cast<__uint128_t>(power_of_ten[1]);
UInt128 approx_upper = static_cast<UInt128>(high64(mantissa)) *
static_cast<UInt128>(power_of_ten[1]);

__uint128_t approx_middle = static_cast<__uint128_t>(high64(mantissa)) *
static_cast<__uint128_t>(power_of_ten[0]) +
static_cast<__uint128_t>(low64(mantissa)) *
static_cast<__uint128_t>(power_of_ten[1]);
UInt128 approx_middle = static_cast<UInt128>(high64(mantissa)) *
static_cast<UInt128>(power_of_ten[0]) +
static_cast<UInt128>(low64(mantissa)) *
static_cast<UInt128>(power_of_ten[1]);

__uint128_t approx_lower = static_cast<__uint128_t>(low64(mantissa)) *
static_cast<__uint128_t>(power_of_ten[0]);
UInt128 approx_lower = static_cast<UInt128>(low64(mantissa)) *
static_cast<UInt128>(power_of_ten[0]);

__uint128_t final_approx_lower =
approx_lower + (static_cast<__uint128_t>(low64(approx_middle)) << 64);
__uint128_t final_approx_upper = approx_upper + high64(approx_middle) +
(final_approx_lower < approx_lower ? 1 : 0);
UInt128 final_approx_lower =
approx_lower + (static_cast<UInt128>(low64(approx_middle)) << 64);
UInt128 final_approx_upper = approx_upper + high64(approx_middle) +
(final_approx_lower < approx_lower ? 1 : 0);

// The halfway constant is used to check if the bits that will be shifted away
// intially are all 1. For 80 bit floats this is 128 (bitstype size) - 64
// (final mantissa size) - 3 (we shift away the last two bits separately for
// accuracy, and the most significant bit is ignored.) = 61 bits. Similarly,
// it's 12 bits for 128 bit floats in this case.
constexpr __uint128_t HALFWAY_CONSTANT =
(__uint128_t(1) << (BITS_IN_MANTISSA -
fputil::FloatProperties<long double>::MANTISSA_WIDTH -
3)) -
constexpr UInt128 HALFWAY_CONSTANT =
(UInt128(1) << (BITS_IN_MANTISSA -
fputil::FloatProperties<long double>::MANTISSA_WIDTH -
3)) -
1;

if ((final_approx_upper & HALFWAY_CONSTANT) == HALFWAY_CONSTANT &&
Expand Down
2 changes: 2 additions & 0 deletions libc/test/src/__support/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ add_libc_unittest(
high_precision_decimal_test.cpp
DEPENDS
libc.src.__support.high_precision_decimal
libc.src.__support.CPP.uint128
)

add_libc_unittest(
Expand All @@ -28,6 +29,7 @@ add_libc_unittest(
str_to_float_test.cpp
DEPENDS
libc.src.__support.str_to_float
libc.src.__support.CPP.uint128
)

add_libc_unittest(
Expand Down
1 change: 1 addition & 0 deletions libc/test/src/__support/CPP/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ add_libc_unittest(
limits_test.cpp
DEPENDS
libc.src.__support.CPP.limits
libc.src.__support.CPP.uint
)

add_libc_unittest(
Expand Down
29 changes: 11 additions & 18 deletions libc/test/src/__support/CPP/limits_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

#include "src/__support/CPP/Limits.h"
#include "src/__support/CPP/UInt.h"
#include "utils/UnitTest/Test.h"

// This just checks against the C spec, almost all implementations will surpass
Expand All @@ -29,23 +30,15 @@ TEST(LlvmLibcLimitsTest, LimitsFollowSpec) {
ULLONG_MAX);
}

TEST(LlvmLibcLimitsTest, UInt128Limits) {
auto umax128 =
__llvm_libc::cpp::NumericLimits<__llvm_libc::cpp::UInt<128>>::max();
auto umax64 = __llvm_libc::cpp::UInt<128>(
__llvm_libc::cpp::NumericLimits<uint64_t>::max());
EXPECT_GT(umax128, umax64);
ASSERT_EQ(~__llvm_libc::cpp::UInt<128>(0), umax128);
#ifdef __SIZEOF_INT128__
// This checks that the current environment supports 128 bit integers.
TEST(LlvmLibcLimitsTest, Int128Works) {
__int128_t max128 = ~__uint128_t(0) >> 1;
__int128_t min128 = (__int128_t(1) << 127);
EXPECT_GT(__llvm_libc::cpp::NumericLimits<__int128_t>::max(),
__int128_t(__llvm_libc::cpp::NumericLimits<long long>::max()));
ASSERT_EQ(__llvm_libc::cpp::NumericLimits<__int128_t>::max(), max128);

EXPECT_LT(__llvm_libc::cpp::NumericLimits<__int128_t>::min(),
__int128_t(__llvm_libc::cpp::NumericLimits<long long>::min()));
ASSERT_EQ(__llvm_libc::cpp::NumericLimits<__int128_t>::min(), min128);

__uint128_t umax128 = ~__uint128_t(0);
EXPECT_GT(
__llvm_libc::cpp::NumericLimits<__uint128_t>::max(),
__uint128_t(__llvm_libc::cpp::NumericLimits<unsigned long long>::max()));
ASSERT_EQ(__llvm_libc::cpp::NumericLimits<__uint128_t>::max(), umax128);
}
ASSERT_EQ(~__uint128_t(0),
__llvm_libc::cpp::NumericLimits<__uint128_t>::max());
#endif
}
30 changes: 9 additions & 21 deletions libc/test/src/__support/high_precision_decimal_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//
//===----------------------------------------------------------------------===//

#include "src/__support/CPP/UInt128.h"
#include "src/__support/high_precision_decimal.h"

#include "utils/UnitTest/Test.h"
Expand Down Expand Up @@ -344,44 +345,34 @@ TEST(LlvmLibcHighPrecisionDecimalTest, RoundingTest) {

EXPECT_EQ(hpd.round_to_integer_type<uint32_t>(), uint32_t(1));
EXPECT_EQ(hpd.round_to_integer_type<uint64_t>(), uint64_t(1));
#ifdef __SIZEOF_INT128__
EXPECT_EQ(hpd.round_to_integer_type<__uint128_t>(), __uint128_t(1));
#endif
EXPECT_EQ(hpd.round_to_integer_type<UInt128>(), UInt128(1));

hpd.shift(1); // shift left 1 to get 2.469 (rounds to 2)

EXPECT_EQ(hpd.round_to_integer_type<uint32_t>(), uint32_t(2));
EXPECT_EQ(hpd.round_to_integer_type<uint64_t>(), uint64_t(2));
#ifdef __SIZEOF_INT128__
EXPECT_EQ(hpd.round_to_integer_type<__uint128_t>(), __uint128_t(2));
#endif
EXPECT_EQ(hpd.round_to_integer_type<UInt128>(), UInt128(2));

hpd.shift(1); // shift left 1 to get 4.938 (rounds to 5)

EXPECT_EQ(hpd.round_to_integer_type<uint32_t>(), uint32_t(5));
EXPECT_EQ(hpd.round_to_integer_type<uint64_t>(), uint64_t(5));
#ifdef __SIZEOF_INT128__
EXPECT_EQ(hpd.round_to_integer_type<__uint128_t>(), __uint128_t(5));
#endif
EXPECT_EQ(hpd.round_to_integer_type<UInt128>(), UInt128(5));

// 2.5 is right between two integers, so we round to even (2)
hpd = __llvm_libc::internal::HighPrecisionDecimal("2.5");

EXPECT_EQ(hpd.round_to_integer_type<uint32_t>(), uint32_t(2));
EXPECT_EQ(hpd.round_to_integer_type<uint64_t>(), uint64_t(2));
#ifdef __SIZEOF_INT128__
EXPECT_EQ(hpd.round_to_integer_type<__uint128_t>(), __uint128_t(2));
#endif
EXPECT_EQ(hpd.round_to_integer_type<UInt128>(), UInt128(2));

// unless it's marked as having truncated, which means it's actually slightly
// higher, forcing a round up (3)
hpd.set_truncated(true);

EXPECT_EQ(hpd.round_to_integer_type<uint32_t>(), uint32_t(3));
EXPECT_EQ(hpd.round_to_integer_type<uint64_t>(), uint64_t(3));
#ifdef __SIZEOF_INT128__
EXPECT_EQ(hpd.round_to_integer_type<__uint128_t>(), __uint128_t(3));
#endif
EXPECT_EQ(hpd.round_to_integer_type<UInt128>(), UInt128(3));

// Check that the larger int types are being handled properly (overflow is not
// handled, so int types that are too small are ignored for this test.)
Expand All @@ -390,16 +381,13 @@ TEST(LlvmLibcHighPrecisionDecimalTest, RoundingTest) {
hpd = __llvm_libc::internal::HighPrecisionDecimal("1099511627776");

EXPECT_EQ(hpd.round_to_integer_type<uint64_t>(), uint64_t(1099511627776));
#ifdef __SIZEOF_INT128__
EXPECT_EQ(hpd.round_to_integer_type<__uint128_t>(),
__uint128_t(1099511627776));
EXPECT_EQ(hpd.round_to_integer_type<UInt128>(), UInt128(1099511627776));

// 1267650600228229401496703205376 = 2^100
hpd = __llvm_libc::internal::HighPrecisionDecimal(
"1267650600228229401496703205376");

__uint128_t result = __uint128_t(1) << 100;
UInt128 result = UInt128(1) << 100;

EXPECT_EQ(hpd.round_to_integer_type<__uint128_t>(), result);
#endif
EXPECT_EQ(hpd.round_to_integer_type<UInt128>(), result);
}
49 changes: 22 additions & 27 deletions libc/test/src/__support/str_to_float_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//
//===----------------------------------------------------------------------===//

#include "src/__support/CPP/UInt128.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/str_to_float.h"

Expand Down Expand Up @@ -273,14 +274,14 @@ TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat80Simple) {
}

TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat80LongerMantissa) {
eisel_lemire_test<long double>((__uint128_t(0x1234567812345678) << 64) +
__uint128_t(0x1234567812345678),
eisel_lemire_test<long double>((UInt128(0x1234567812345678) << 64) +
UInt128(0x1234567812345678),
0, 0x91a2b3c091a2b3c1, 16507);
eisel_lemire_test<long double>((__uint128_t(0x1234567812345678) << 64) +
__uint128_t(0x1234567812345678),
eisel_lemire_test<long double>((UInt128(0x1234567812345678) << 64) +
UInt128(0x1234567812345678),
300, 0xd97757de56adb65c, 17503);
eisel_lemire_test<long double>((__uint128_t(0x1234567812345678) << 64) +
__uint128_t(0x1234567812345678),
eisel_lemire_test<long double>((UInt128(0x1234567812345678) << 64) +
UInt128(0x1234567812345678),
-300, 0xc30feb9a7618457d, 15510);
}

Expand All @@ -299,7 +300,7 @@ TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat80TableLimits) {

TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat80Fallback) {
uint32_t outputExp2 = 0;
__uint128_t quadOutputMantissa = 0;
UInt128 quadOutputMantissa = 0;

// This number is halfway between two possible results, and the algorithm
// can't determine which is correct.
Expand All @@ -313,39 +314,33 @@ TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat80Fallback) {
ASSERT_FALSE(__llvm_libc::internal::eisel_lemire<long double>(
1, -1000, &quadOutputMantissa, &outputExp2));
}
#elif defined(__SIZEOF_INT128__)
#else // Quad precision long double
TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat128Simple) {
eisel_lemire_test<long double>(123, 0, (__uint128_t(0x1ec0000000000) << 64),
eisel_lemire_test<long double>(123, 0, (UInt128(0x1ec0000000000) << 64),
16389);
eisel_lemire_test<long double>(12345678901234568192u, 0,
(__uint128_t(0x156a95319d63e) << 64) +
__uint128_t(0x1800000000000000),
16446);
eisel_lemire_test<long double>(
12345678901234568192u, 0,
(UInt128(0x156a95319d63e) << 64) + UInt128(0x1800000000000000), 16446);
}

TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat128LongerMantissa) {
eisel_lemire_test<long double>(
(__uint128_t(0x1234567812345678) << 64) + __uint128_t(0x1234567812345678),
0, (__uint128_t(0x1234567812345) << 64) + __uint128_t(0x6781234567812345),
16507);
(UInt128(0x1234567812345678) << 64) + UInt128(0x1234567812345678), 0,
(UInt128(0x1234567812345) << 64) + UInt128(0x6781234567812345), 16507);
eisel_lemire_test<long double>(
(__uint128_t(0x1234567812345678) << 64) + __uint128_t(0x1234567812345678),
300,
(__uint128_t(0x1b2eeafbcad5b) << 64) + __uint128_t(0x6cb8b4451dfcde19),
17503);
(UInt128(0x1234567812345678) << 64) + UInt128(0x1234567812345678), 300,
(UInt128(0x1b2eeafbcad5b) << 64) + UInt128(0x6cb8b4451dfcde19), 17503);
eisel_lemire_test<long double>(
(__uint128_t(0x1234567812345678) << 64) + __uint128_t(0x1234567812345678),
-300,
(__uint128_t(0x1861fd734ec30) << 64) + __uint128_t(0x8afa7189f0f7595f),
15510);
(UInt128(0x1234567812345678) << 64) + UInt128(0x1234567812345678), -300,
(UInt128(0x1861fd734ec30) << 64) + UInt128(0x8afa7189f0f7595f), 15510);
}

TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat128Fallback) {
uint32_t outputExp2 = 0;
__uint128_t quadOutputMantissa = 0;
UInt128 quadOutputMantissa = 0;

ASSERT_FALSE(__llvm_libc::internal::eisel_lemire<long double>(
(__uint128_t(0x5ce0e9a56015fec5) << 64) + __uint128_t(0xaadfa328ae39b333),
1, &quadOutputMantissa, &outputExp2));
(UInt128(0x5ce0e9a56015fec5) << 64) + UInt128(0xaadfa328ae39b333), 1,
&quadOutputMantissa, &outputExp2));
}
#endif
131 changes: 70 additions & 61 deletions libc/test/src/__support/uint128_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,149 +10,158 @@

#include "utils/UnitTest/Test.h"

using UInt128 = __llvm_libc::cpp::UInt<128>;
// We want to test __llvm_libc::cpp::UInt<128> explicitly. So, for convenience,
// we use a sugar which does not conflict with the UInt128 type which can
// resolve to __uint128_t if the platform has it.
using LL_UInt128 = __llvm_libc::cpp::UInt<128>;

TEST(LlvmLibcUInt128ClassTest, BasicInit) {
UInt128 empty;
UInt128 half_val(12345);
UInt128 full_val({12345, 67890});
LL_UInt128 empty;
LL_UInt128 half_val(12345);
LL_UInt128 full_val({12345, 67890});
ASSERT_TRUE(half_val != full_val);
}

TEST(LlvmLibcUInt128ClassTest, AdditionTests) {
UInt128 val1(12345);
UInt128 val2(54321);
UInt128 result1(66666);
LL_UInt128 val1(12345);
LL_UInt128 val2(54321);
LL_UInt128 result1(66666);
EXPECT_EQ(val1 + val2, result1);
EXPECT_EQ((val1 + val2), (val2 + val1)); // addition is reciprocal

// Test overflow
UInt128 val3({0xf000000000000001, 0});
UInt128 val4({0x100000000000000f, 0});
UInt128 result2({0x10, 0x1});
LL_UInt128 val3({0xf000000000000001, 0});
LL_UInt128 val4({0x100000000000000f, 0});
LL_UInt128 result2({0x10, 0x1});
EXPECT_EQ(val3 + val4, result2);
EXPECT_EQ(val3 + val4, val4 + val3);
}

TEST(LlvmLibcUInt128ClassTest, MultiplicationTests) {
UInt128 val1({5, 0});
UInt128 val2({10, 0});
UInt128 result1({50, 0});
LL_UInt128 val1({5, 0});
LL_UInt128 val2({10, 0});
LL_UInt128 result1({50, 0});
EXPECT_EQ((val1 * val2), result1);
EXPECT_EQ((val1 * val2), (val2 * val1)); // multiplication is reciprocal

// Check that the multiplication works accross the whole number
UInt128 val3({0xf, 0});
UInt128 val4({0x1111111111111111, 0x1111111111111111});
UInt128 result2({0xffffffffffffffff, 0xffffffffffffffff});
LL_UInt128 val3({0xf, 0});
LL_UInt128 val4({0x1111111111111111, 0x1111111111111111});
LL_UInt128 result2({0xffffffffffffffff, 0xffffffffffffffff});
EXPECT_EQ((val3 * val4), result2);
EXPECT_EQ((val3 * val4), (val4 * val3));

// Check that multiplication doesn't reorder the bits.
UInt128 val5({2, 0});
UInt128 val6({0x1357024675316420, 0x0123456776543210});
UInt128 result3({0x26ae048cea62c840, 0x02468aceeca86420});
LL_UInt128 val5({2, 0});
LL_UInt128 val6({0x1357024675316420, 0x0123456776543210});
LL_UInt128 result3({0x26ae048cea62c840, 0x02468aceeca86420});

EXPECT_EQ((val5 * val6), result3);
EXPECT_EQ((val5 * val6), (val6 * val5));

// Make sure that multiplication handles overflow correctly.
UInt128 val7(2);
UInt128 val8({0x8000800080008000, 0x8000800080008000});
UInt128 result4({0x0001000100010000, 0x0001000100010001});
LL_UInt128 val7(2);
LL_UInt128 val8({0x8000800080008000, 0x8000800080008000});
LL_UInt128 result4({0x0001000100010000, 0x0001000100010001});
EXPECT_EQ((val7 * val8), result4);
EXPECT_EQ((val7 * val8), (val8 * val7));

// val9 is the 128 bit mantissa of 1e60 as a float, val10 is the mantissa for
// 1e-60. They almost cancel on the high bits, but the result we're looking
// for is just the low bits. The full result would be
// 0x7fffffffffffffffffffffffffffffff3a4f32d17f40d08f917cf11d1e039c50
UInt128 val9({0x01D762422C946590, 0x9F4F2726179A2245});
UInt128 val10({0x3792F412CB06794D, 0xCDB02555653131B6});
UInt128 result5({0x917cf11d1e039c50, 0x3a4f32d17f40d08f});
LL_UInt128 val9({0x01D762422C946590, 0x9F4F2726179A2245});
LL_UInt128 val10({0x3792F412CB06794D, 0xCDB02555653131B6});
LL_UInt128 result5({0x917cf11d1e039c50, 0x3a4f32d17f40d08f});
EXPECT_EQ((val9 * val10), result5);
EXPECT_EQ((val9 * val10), (val10 * val9));
}

TEST(LlvmLibcUInt128ClassTest, ShiftLeftTests) {
UInt128 val1(0x0123456789abcdef);
UInt128 result1(0x123456789abcdef0);
LL_UInt128 val1(0x0123456789abcdef);
LL_UInt128 result1(0x123456789abcdef0);
EXPECT_EQ((val1 << 4), result1);

UInt128 val2({0x13579bdf02468ace, 0x123456789abcdef0});
UInt128 result2({0x02468ace00000000, 0x9abcdef013579bdf});
LL_UInt128 val2({0x13579bdf02468ace, 0x123456789abcdef0});
LL_UInt128 result2({0x02468ace00000000, 0x9abcdef013579bdf});
EXPECT_EQ((val2 << 32), result2);
LL_UInt128 val22 = val2;
val22 <<= 32;
EXPECT_EQ(val22, result2);

UInt128 result3({0, 0x13579bdf02468ace});
LL_UInt128 result3({0, 0x13579bdf02468ace});
EXPECT_EQ((val2 << 64), result3);

UInt128 result4({0, 0x02468ace00000000});
LL_UInt128 result4({0, 0x02468ace00000000});
EXPECT_EQ((val2 << 96), result4);

UInt128 result5({0, 0x2468ace000000000});
LL_UInt128 result5({0, 0x2468ace000000000});
EXPECT_EQ((val2 << 100), result5);

UInt128 result6({0, 0});
LL_UInt128 result6({0, 0});
EXPECT_EQ((val2 << 128), result6);
EXPECT_EQ((val2 << 256), result6);
}

TEST(LlvmLibcUInt128ClassTest, ShiftRightTests) {
UInt128 val1(0x0123456789abcdef);
UInt128 result1(0x00123456789abcde);
LL_UInt128 val1(0x0123456789abcdef);
LL_UInt128 result1(0x00123456789abcde);
EXPECT_EQ((val1 >> 4), result1);

UInt128 val2({0x13579bdf02468ace, 0x123456789abcdef0});
UInt128 result2({0x9abcdef013579bdf, 0x0000000012345678});
LL_UInt128 val2({0x13579bdf02468ace, 0x123456789abcdef0});
LL_UInt128 result2({0x9abcdef013579bdf, 0x0000000012345678});
EXPECT_EQ((val2 >> 32), result2);
LL_UInt128 val22 = val2;
val22 >>= 32;
EXPECT_EQ(val22, result2);

UInt128 result3({0x123456789abcdef0, 0});
LL_UInt128 result3({0x123456789abcdef0, 0});
EXPECT_EQ((val2 >> 64), result3);

UInt128 result4({0x0000000012345678, 0});
LL_UInt128 result4({0x0000000012345678, 0});
EXPECT_EQ((val2 >> 96), result4);

UInt128 result5({0x0000000001234567, 0});
LL_UInt128 result5({0x0000000001234567, 0});
EXPECT_EQ((val2 >> 100), result5);

UInt128 result6({0, 0});
LL_UInt128 result6({0, 0});
EXPECT_EQ((val2 >> 128), result6);
EXPECT_EQ((val2 >> 256), result6);
}

TEST(LlvmLibcUInt128ClassTest, AndTests) {
UInt128 base({0xffff00000000ffff, 0xffffffff00000000});
UInt128 val128({0xf0f0f0f00f0f0f0f, 0xff00ff0000ff00ff});
LL_UInt128 base({0xffff00000000ffff, 0xffffffff00000000});
LL_UInt128 val128({0xf0f0f0f00f0f0f0f, 0xff00ff0000ff00ff});
uint64_t val64 = 0xf0f0f0f00f0f0f0f;
int val32 = 0x0f0f0f0f;
UInt128 result128({0xf0f0000000000f0f, 0xff00ff0000000000});
UInt128 result64(0xf0f0000000000f0f);
UInt128 result32(0x00000f0f);
LL_UInt128 result128({0xf0f0000000000f0f, 0xff00ff0000000000});
LL_UInt128 result64(0xf0f0000000000f0f);
LL_UInt128 result32(0x00000f0f);
EXPECT_EQ((base & val128), result128);
EXPECT_EQ((base & val64), result64);
EXPECT_EQ((base & val32), result32);
}

TEST(LlvmLibcUInt128ClassTest, OrTests) {
UInt128 base({0xffff00000000ffff, 0xffffffff00000000});
UInt128 val128({0xf0f0f0f00f0f0f0f, 0xff00ff0000ff00ff});
LL_UInt128 base({0xffff00000000ffff, 0xffffffff00000000});
LL_UInt128 val128({0xf0f0f0f00f0f0f0f, 0xff00ff0000ff00ff});
uint64_t val64 = 0xf0f0f0f00f0f0f0f;
int val32 = 0x0f0f0f0f;
UInt128 result128({0xfffff0f00f0fffff, 0xffffffff00ff00ff});
UInt128 result64({0xfffff0f00f0fffff, 0xffffffff00000000});
UInt128 result32({0xffff00000f0fffff, 0xffffffff00000000});
LL_UInt128 result128({0xfffff0f00f0fffff, 0xffffffff00ff00ff});
LL_UInt128 result64({0xfffff0f00f0fffff, 0xffffffff00000000});
LL_UInt128 result32({0xffff00000f0fffff, 0xffffffff00000000});
EXPECT_EQ((base | val128), result128);
EXPECT_EQ((base | val64), result64);
EXPECT_EQ((base | val32), result32);
}

TEST(LlvmLibcUInt128ClassTest, EqualsTests) {
UInt128 a1({0xffffffff00000000, 0xffff00000000ffff});
UInt128 a2({0xffffffff00000000, 0xffff00000000ffff});
UInt128 b({0xff00ff0000ff00ff, 0xf0f0f0f00f0f0f0f});
UInt128 a_reversed({0xffff00000000ffff, 0xffffffff00000000});
UInt128 a_upper(0xffff00000000ffff);
UInt128 a_lower(0xffffffff00000000);
LL_UInt128 a1({0xffffffff00000000, 0xffff00000000ffff});
LL_UInt128 a2({0xffffffff00000000, 0xffff00000000ffff});
LL_UInt128 b({0xff00ff0000ff00ff, 0xf0f0f0f00f0f0f0f});
LL_UInt128 a_reversed({0xffff00000000ffff, 0xffffffff00000000});
LL_UInt128 a_upper(0xffff00000000ffff);
LL_UInt128 a_lower(0xffffffff00000000);
ASSERT_TRUE(a1 == a1);
ASSERT_TRUE(a1 == a2);
ASSERT_FALSE(a1 == b);
Expand All @@ -163,15 +172,15 @@ TEST(LlvmLibcUInt128ClassTest, EqualsTests) {
}

TEST(LlvmLibcUInt128ClassTest, ComparisonTests) {
UInt128 a({0xffffffff00000000, 0xffff00000000ffff});
UInt128 b({0xff00ff0000ff00ff, 0xf0f0f0f00f0f0f0f});
LL_UInt128 a({0xffffffff00000000, 0xffff00000000ffff});
LL_UInt128 b({0xff00ff0000ff00ff, 0xf0f0f0f00f0f0f0f});
EXPECT_GT(a, b);
EXPECT_GE(a, b);
EXPECT_LT(b, a);
EXPECT_LE(b, a);

UInt128 x(0xffffffff00000000);
UInt128 y(0x00000000ffffffff);
LL_UInt128 x(0xffffffff00000000);
LL_UInt128 y(0x00000000ffffffff);
EXPECT_GT(x, y);
EXPECT_GE(x, y);
EXPECT_LT(y, x);
Expand Down
1 change: 1 addition & 0 deletions libc/test/src/stdlib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ add_libc_unittest(
SRCS
strtold_test.cpp
DEPENDS
libc.src.__support.CPP.uint128
libc.src.stdlib.strtold
)

Expand Down
163 changes: 75 additions & 88 deletions libc/test/src/stdlib/strtold_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//
//===----------------------------------------------------------------------===//

#include "src/__support/CPP/UInt128.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/stdlib/strtold.h"

Expand All @@ -30,7 +31,7 @@ class LlvmLibcStrToLDTest : public __llvm_libc::testing::Test {
const uint64_t expectedRawData, const int expectedErrno = 0)
#else
void run_test(const char *inputString, const ptrdiff_t expectedStrLen,
const __uint128_t expectedRawData, const int expectedErrno = 0)
const UInt128 expectedRawData, const int expectedErrno = 0)
#endif
{
// expectedRawData64 is the expected long double result as a uint64_t,
Expand All @@ -46,7 +47,7 @@ class LlvmLibcStrToLDTest : public __llvm_libc::testing::Test {
// |
// +-- 11 Exponent Bits

// expectedRawData80 is the expected long double result as a __uint128_t,
// expectedRawData80 is the expected long double result as a UInt128,
// organized according to the x86 extended precision format:
//
// +-- 1 Sign Bit
Expand All @@ -59,7 +60,7 @@ class LlvmLibcStrToLDTest : public __llvm_libc::testing::Test {
// | |
// +-- 15 Exponent Bits +-- 63 Mantissa bits

// expectedRawData128 is the expected long double result as a __uint128_t,
// expectedRawData128 is the expected long double result as a UInt128,
// organized according to IEEE754 quadruple precision format:
//
// +-- 1 Sign Bit +-- 112 Mantissa bits
Expand Down Expand Up @@ -97,168 +98,154 @@ class LlvmLibcStrToLDTest : public __llvm_libc::testing::Test {
TEST_F(LlvmLibcStrToLDTest, SimpleTest) {
run_test("123", 3,
SELECT_CONST(uint64_t(0x405ec00000000000),
__uint128_t(0x4005f60000) << 40,
__uint128_t(0x4005ec0000000000) << 64));
UInt128(0x4005f60000) << 40,
UInt128(0x4005ec0000000000) << 64));

// This should fail on Eisel-Lemire, forcing a fallback to simple decimal
// conversion.
run_test("12345678901234549760", 20,
SELECT_CONST(uint64_t(0x43e56a95319d63d8),
(__uint128_t(0x403eab54a9) << 40) +
__uint128_t(0x8ceb1ec400),
(__uint128_t(0x403e56a95319d63d) << 64) +
__uint128_t(0x8800000000000000)));
(UInt128(0x403eab54a9) << 40) + UInt128(0x8ceb1ec400),
(UInt128(0x403e56a95319d63d) << 64) +
UInt128(0x8800000000000000)));

// Found while looking for difficult test cases here:
// https://github.com/nigeltao/parse-number-fxx-test-data/blob/main/more-test-cases/golang-org-issue-36657.txt
run_test("1090544144181609348835077142190", 31,
SELECT_CONST(uint64_t(0x462b8779f2474dfb),
(__uint128_t(0x4062dc3bcf) << 40) +
__uint128_t(0x923a6fd402),
(__uint128_t(0x4062b8779f2474df) << 64) +
__uint128_t(0xa804bfd8c6d5c000)));
(UInt128(0x4062dc3bcf) << 40) + UInt128(0x923a6fd402),
(UInt128(0x4062b8779f2474df) << 64) +
UInt128(0xa804bfd8c6d5c000)));

run_test("0x123", 5,
SELECT_CONST(uint64_t(0x4072300000000000),
(__uint128_t(0x4007918000) << 40),
(__uint128_t(0x4007230000000000) << 64)));
(UInt128(0x4007918000) << 40),
(UInt128(0x4007230000000000) << 64)));
}

// These are tests that have caused problems for doubles in the past.
TEST_F(LlvmLibcStrToLDTest, Float64SpecificFailures) {
run_test("3E70000000000000", 16,
SELECT_CONST(uint64_t(0x7FF0000000000000),
(__uint128_t(0x7fff800000) << 40),
(__uint128_t(0x7fff000000000000) << 64)),
(UInt128(0x7fff800000) << 40),
(UInt128(0x7fff000000000000) << 64)),
ERANGE);
run_test("358416272e-33", 13,
SELECT_CONST(uint64_t(0x3adbbb2a68c9d0b9),
(__uint128_t(0x3fadddd953) << 40) +
__uint128_t(0x464e85c400),
(__uint128_t(0x3fadbbb2a68c9d0b) << 64) +
__uint128_t(0x8800e7969e1c5fc8)));
(UInt128(0x3fadddd953) << 40) + UInt128(0x464e85c400),
(UInt128(0x3fadbbb2a68c9d0b) << 64) +
UInt128(0x8800e7969e1c5fc8)));
run_test("2.16656806400000023841857910156251e9", 36,
SELECT_CONST(uint64_t(0x41e0246690000001),
(__uint128_t(0x401e812334) << 40) +
__uint128_t(0x8000000400),
(__uint128_t(0x401e024669000000) << 64) +
__uint128_t(0x800000000000018)));
(UInt128(0x401e812334) << 40) + UInt128(0x8000000400),
(UInt128(0x401e024669000000) << 64) +
UInt128(0x800000000000018)));
run_test("27949676547093071875", 20,
SELECT_CONST(uint64_t(0x43f83e132bc608c9),
(__uint128_t(0x403fc1f099) << 40) +
__uint128_t(0x5e30464402),
(__uint128_t(0x403f83e132bc608c) << 64) +
__uint128_t(0x8803000000000000)));
(UInt128(0x403fc1f099) << 40) + UInt128(0x5e30464402),
(UInt128(0x403f83e132bc608c) << 64) +
UInt128(0x8803000000000000)));
}

TEST_F(LlvmLibcStrToLDTest, MaxSizeNumbers) {
run_test("1.1897314953572317650e4932", 26,
SELECT_CONST(uint64_t(0x7FF0000000000000),
(__uint128_t(0x7ffeffffff) << 40) +
__uint128_t(0xffffffffff),
(__uint128_t(0x7ffeffffffffffff) << 64) +
__uint128_t(0xfffd57322e3f8675)),
(UInt128(0x7ffeffffff) << 40) + UInt128(0xffffffffff),
(UInt128(0x7ffeffffffffffff) << 64) +
UInt128(0xfffd57322e3f8675)),
SELECT_CONST(ERANGE, 0, 0));
run_test("1.18973149535723176508e4932", 27,
SELECT_CONST(uint64_t(0x7FF0000000000000),
(__uint128_t(0x7fff800000) << 40),
(__uint128_t(0x7ffeffffffffffff) << 64) +
__uint128_t(0xffffd2478338036c)),
(UInt128(0x7fff800000) << 40),
(UInt128(0x7ffeffffffffffff) << 64) +
UInt128(0xffffd2478338036c)),
SELECT_CONST(ERANGE, ERANGE, 0));
}

// These tests check subnormal behavior for 80 bit and 128 bit floats. They will
// be too small for 64 bit floats.
TEST_F(LlvmLibcStrToLDTest, SubnormalTests) {
run_test("1e-4950", 7,
SELECT_CONST(uint64_t(0), (__uint128_t(0x00000000000000000003)),
(__uint128_t(0x000000000000000000057c9647e1a018))),
SELECT_CONST(uint64_t(0), (UInt128(0x00000000000000000003)),
(UInt128(0x000000000000000000057c9647e1a018))),
ERANGE);
run_test("1.89e-4951", 10,
SELECT_CONST(uint64_t(0), (__uint128_t(0x00000000000000000001)),
(__uint128_t(0x0000000000000000000109778a006738))),
SELECT_CONST(uint64_t(0), (UInt128(0x00000000000000000001)),
(UInt128(0x0000000000000000000109778a006738))),
ERANGE);
run_test("4e-4966", 7,
SELECT_CONST(uint64_t(0), (__uint128_t(0)),
(__uint128_t(0x00000000000000000000000000000001))),
SELECT_CONST(uint64_t(0), (UInt128(0)),
(UInt128(0x00000000000000000000000000000001))),
ERANGE);
}

TEST_F(LlvmLibcStrToLDTest, SmallNormalTests) {
run_test(
"3.37e-4932", 10,
SELECT_CONST(uint64_t(0),
(__uint128_t(0x1804cf7) << 40) + __uint128_t(0x908850712),
(__uint128_t(0x10099ee12110a) << 64) +
__uint128_t(0xe24b75c0f50dc0c)),
SELECT_CONST(ERANGE, 0, 0));
run_test("3.37e-4932", 10,
SELECT_CONST(
uint64_t(0), (UInt128(0x1804cf7) << 40) + UInt128(0x908850712),
(UInt128(0x10099ee12110a) << 64) + UInt128(0xe24b75c0f50dc0c)),
SELECT_CONST(ERANGE, 0, 0));
}

TEST_F(LlvmLibcStrToLDTest, ComplexHexadecimalTests) {
run_test("0x1p16383", 9,
SELECT_CONST(0x7ff0000000000000, (__uint128_t(0x7ffe800000) << 40),
(__uint128_t(0x7ffe000000000000) << 64)),
SELECT_CONST(0x7ff0000000000000, (UInt128(0x7ffe800000) << 40),
(UInt128(0x7ffe000000000000) << 64)),
SELECT_CONST(ERANGE, 0, 0));
run_test("0x123456789abcdef", 17,
SELECT_CONST(0x43723456789abcdf,
(__uint128_t(0x403791a2b3) << 40) +
__uint128_t(0xc4d5e6f780),
(__uint128_t(0x403723456789abcd) << 64) +
__uint128_t(0xef00000000000000)));
(UInt128(0x403791a2b3) << 40) + UInt128(0xc4d5e6f780),
(UInt128(0x403723456789abcd) << 64) +
UInt128(0xef00000000000000)));
run_test("0x123456789abcdef0123456789ABCDEF", 33,
SELECT_CONST(0x47723456789abcdf,
(__uint128_t(0x407791a2b3) << 40) +
__uint128_t(0xc4d5e6f781),
(__uint128_t(0x407723456789abcd) << 64) +
__uint128_t(0xef0123456789abce)));
(UInt128(0x407791a2b3) << 40) + UInt128(0xc4d5e6f781),
(UInt128(0x407723456789abcd) << 64) +
UInt128(0xef0123456789abce)));
}

TEST_F(LlvmLibcStrToLDTest, InfTests) {
run_test("INF", 3,
SELECT_CONST(0x7ff0000000000000, (__uint128_t(0x7fff800000) << 40),
(__uint128_t(0x7fff000000000000) << 64)));
SELECT_CONST(0x7ff0000000000000, (UInt128(0x7fff800000) << 40),
(UInt128(0x7fff000000000000) << 64)));
run_test("INFinity", 8,
SELECT_CONST(0x7ff0000000000000, (__uint128_t(0x7fff800000) << 40),
(__uint128_t(0x7fff000000000000) << 64)));
SELECT_CONST(0x7ff0000000000000, (UInt128(0x7fff800000) << 40),
(UInt128(0x7fff000000000000) << 64)));
run_test("-inf", 4,
SELECT_CONST(0xfff0000000000000, (__uint128_t(0xffff800000) << 40),
(__uint128_t(0xffff000000000000) << 64)));
SELECT_CONST(0xfff0000000000000, (UInt128(0xffff800000) << 40),
(UInt128(0xffff000000000000) << 64)));
}

TEST_F(LlvmLibcStrToLDTest, NaNTests) {
run_test("NaN", 3,
SELECT_CONST(0x7ff8000000000000, (__uint128_t(0x7fffc00000) << 40),
(__uint128_t(0x7fff800000000000) << 64)));
SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
(UInt128(0x7fff800000000000) << 64)));
run_test("-nAn", 4,
SELECT_CONST(0xfff8000000000000, (__uint128_t(0xffffc00000) << 40),
(__uint128_t(0xffff800000000000) << 64)));
SELECT_CONST(0xfff8000000000000, (UInt128(0xffffc00000) << 40),
(UInt128(0xffff800000000000) << 64)));
run_test("NaN()", 5,
SELECT_CONST(0x7ff8000000000000, (__uint128_t(0x7fffc00000) << 40),
(__uint128_t(0x7fff800000000000) << 64)));
SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
(UInt128(0x7fff800000000000) << 64)));
run_test("NaN(1234)", 9,
SELECT_CONST(0x7ff80000000004d2,
(__uint128_t(0x7fffc00000) << 40) + __uint128_t(0x4d2),
(__uint128_t(0x7fff800000000000) << 64) +
__uint128_t(0x4d2)));
(UInt128(0x7fffc00000) << 40) + UInt128(0x4d2),
(UInt128(0x7fff800000000000) << 64) + UInt128(0x4d2)));
run_test("NaN(0xffffffffffff)", 19,
SELECT_CONST(0x7ff8ffffffffffff,
(__uint128_t(0x7fffc000ff) << 40) +
__uint128_t(0xffffffffff),
(__uint128_t(0x7fff800000000000) << 64) +
__uint128_t(0xffffffffffff)));
(UInt128(0x7fffc000ff) << 40) + UInt128(0xffffffffff),
(UInt128(0x7fff800000000000) << 64) +
UInt128(0xffffffffffff)));
run_test("NaN(0xfffffffffffff)", 20,
SELECT_CONST(0x7fffffffffffffff,
(__uint128_t(0x7fffc00fff) << 40) +
__uint128_t(0xffffffffff),
(__uint128_t(0x7fff800000000000) << 64) +
__uint128_t(0xfffffffffffff)));
(UInt128(0x7fffc00fff) << 40) + UInt128(0xffffffffff),
(UInt128(0x7fff800000000000) << 64) +
UInt128(0xfffffffffffff)));
run_test("NaN(0xffffffffffffffff)", 23,
SELECT_CONST(0x7fffffffffffffff,
(__uint128_t(0x7fffffffff) << 40) +
__uint128_t(0xffffffffff),
(__uint128_t(0x7fff800000000000) << 64) +
__uint128_t(0xffffffffffffffff)));
(UInt128(0x7fffffffff) << 40) + UInt128(0xffffffffff),
(UInt128(0x7fff800000000000) << 64) +
UInt128(0xffffffffffffffff)));
run_test("NaN( 1234)", 3,
SELECT_CONST(0x7ff8000000000000, (__uint128_t(0x7fffc00000) << 40),
(__uint128_t(0x7fff800000000000) << 64)));
SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
(UInt128(0x7fff800000000000) << 64)));
}
5 changes: 3 additions & 2 deletions libc/utils/UnitTest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ add_library(
LibcTest.h
)
target_include_directories(LibcUnitTest PUBLIC ${LIBC_SOURCE_DIR})
add_dependencies(LibcUnitTest libc.src.__support.CPP.type_traits)
add_dependencies(LibcUnitTest libc.src.__support.CPP.type_traits libc.src.__support.CPP.uint128)
target_link_libraries(LibcUnitTest PUBLIC libc_test_utils)

add_library(
Expand Down Expand Up @@ -71,6 +71,7 @@ target_link_libraries(LibcPrintfHelpers LibcUnitTest)
add_dependencies(
LibcPrintfHelpers
LibcUnitTest
libc.utils.UnitTest.string_utils
libc.src.__support.CPP.uint128
libc.src.stdio.printf_core.core_structs
libc.utils.UnitTest.string_utils
)
52 changes: 23 additions & 29 deletions libc/utils/UnitTest/LibcTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

#include "LibcTest.h"

#include "src/__support/CPP/UInt.h"
#include "src/__support/CPP/UInt128.h"
#include "utils/testutils/ExecuteFunction.h"
#include <cassert>
#include <iostream>
Expand Down Expand Up @@ -42,11 +42,15 @@ describeValue(ValType Value) {
}

std::string describeValue(std::string Value) { return std::string(Value); }
#ifdef __SIZEOF_INT128__
// When the value is __uint128_t, also show its hexadecimal digits.
// Using template to force exact match, prevent ambiguous promotion.
std::string describeValue128(__uint128_t Value) {
std::string S(sizeof(__uint128_t) * 2, '0');

// When the value is UInt128 or __uint128_t, show its hexadecimal digits.
// We cannot just use a UInt128 specialization as that resolves to only
// one type, UInt<128> or __uint128_t. We want both overloads as we want to
// be able to unittest UInt<128> on platforms where UInt128 resolves to
// UInt128.
template <typename UInt128Type>
std::string describeValue128(UInt128Type Value) {
std::string S(sizeof(UInt128) * 2, '0');

for (auto I = S.rbegin(), End = S.rend(); I != End; ++I, Value >>= 4) {
unsigned char Mod = static_cast<unsigned char>(Value) & 15;
Expand All @@ -56,26 +60,16 @@ std::string describeValue128(__uint128_t Value) {
return "0x" + S;
}

template <> std::string describeValue<__int128_t>(__int128_t Value) {
return describeValue128(Value);
}
#ifdef __SIZEOF_INT128__
template <> std::string describeValue<__uint128_t>(__uint128_t Value) {
return describeValue128(Value);
}
#endif

// When the value is UInt<128>, also show its hexadecimal digits.
template <>
std::string
describeValue<__llvm_libc::cpp::UInt<128>>(__llvm_libc::cpp::UInt<128> Value) {
std::string S(sizeof(__llvm_libc::cpp::UInt<128>) * 2, '0');

for (auto I = S.rbegin(), End = S.rend(); I != End; ++I, Value = Value >> 4) {
unsigned char Mod = static_cast<unsigned char>(Value) & 15;
*I = Mod < 10 ? '0' + Mod : 'a' + Mod - 10;
}

return "0x" + S;
return describeValue128(Value);
}

template <typename ValType>
Expand Down Expand Up @@ -234,17 +228,6 @@ template bool test<long long>(RunContext *Ctx, TestCondition Cond,
const char *RHSStr, const char *File,
unsigned long Line);

#ifdef __SIZEOF_INT128__
template bool test<__int128_t>(RunContext *Ctx, TestCondition Cond,
__int128_t LHS, __int128_t RHS,
const char *LHSStr, const char *RHSStr,
const char *File, unsigned long Line);
#endif
template bool test<__llvm_libc::cpp::UInt<128>>(
RunContext *Ctx, TestCondition Cond, __llvm_libc::cpp::UInt<128> LHS,
__llvm_libc::cpp::UInt<128> RHS, const char *LHSStr, const char *RHSStr,
const char *File, unsigned long Line);

template bool test<unsigned char>(RunContext *Ctx, TestCondition Cond,
unsigned char LHS, unsigned char RHS,
const char *LHSStr, const char *RHSStr,
Expand Down Expand Up @@ -275,13 +258,24 @@ template bool test<unsigned long long>(RunContext *Ctx, TestCondition Cond,
const char *LHSStr, const char *RHSStr,
const char *File, unsigned long Line);

// We cannot just use a single UInt128 specialization as that resolves to only
// one type, UInt<128> or __uint128_t. We want both overloads as we want to
// be able to unittest UInt<128> on platforms where UInt128 resolves to
// UInt128.
#ifdef __SIZEOF_INT128__
// When builtin __uint128_t type is available, include its specialization
// also.
template bool test<__uint128_t>(RunContext *Ctx, TestCondition Cond,
__uint128_t LHS, __uint128_t RHS,
const char *LHSStr, const char *RHSStr,
const char *File, unsigned long Line);
#endif

template bool test<__llvm_libc::cpp::UInt<128>>(
RunContext *Ctx, TestCondition Cond, __llvm_libc::cpp::UInt<128> LHS,
__llvm_libc::cpp::UInt<128> RHS, const char *LHSStr, const char *RHSStr,
const char *File, unsigned long Line);

} // namespace internal

bool Test::testStrEq(const char *LHS, const char *RHS, const char *LHSStr,
Expand Down
5 changes: 3 additions & 2 deletions libc/utils/UnitTest/PrintfMatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
//===----------------------------------------------------------------------===//

#include "PrintfMatcher.h"

#include "src/__support/CPP/UInt128.h"
#include "src/stdio/printf_core/core_structs.h"

#include "utils/UnitTest/StringUtils.h"
Expand Down Expand Up @@ -70,8 +72,7 @@ void display(testutils::StreamWrapper &stream, FormatSection form) {
reinterpret_cast<uintptr_t>(form.conv_val_ptr))
<< "\n";
else if (form.conv_name != '%')
stream << "\tvalue: " << int_to_hex<__uint128_t>(form.conv_val_raw)
<< "\n";
stream << "\tvalue: " << int_to_hex<UInt128>(form.conv_val_raw) << "\n";
}
}
} // anonymous namespace
Expand Down
13 changes: 12 additions & 1 deletion utils/bazel/llvm-project-overlay/libc/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ cc_library(
cc_library(
name = "__support_cpp_limits",
hdrs = ["src/__support/CPP/Limits.h"],
deps = [":libc_root"],
deps = [":libc_root", "__support_cpp_uint"],
)

cc_library(
Expand All @@ -89,6 +89,14 @@ cc_library(
deps = [":libc_root","__support_cpp_array"],
)

cc_library(
name = "__support_cpp_uint128",
hdrs = [
"src/__support/CPP/UInt128.h",
],
deps = [":libc_root",":__support_cpp_uint"],
)

cc_library(
name = "__support_cpp_type_traits",
hdrs = [
Expand Down Expand Up @@ -174,6 +182,7 @@ cc_library(
":__support_common",
":__support_cpp_bit",
":__support_cpp_type_traits",
":__support_cpp_uint128",
":libc_root",
],
)
Expand Down Expand Up @@ -201,6 +210,7 @@ cc_library(
":__support_common",
":__support_cpp_bit",
":__support_cpp_type_traits",
":__support_cpp_uint128",
":__support_fputil",
":libc_root",
],
Expand All @@ -226,6 +236,7 @@ cc_library(
":__support_common",
":__support_cpp_bit",
":__support_cpp_type_traits",
":__support_cpp_uint128",
":__support_fputil",
":libc_root",
],
Expand Down