[libc] [llvm] [libc] Refactor `BigInt` (PR #86137)
Guillaume Chatelet via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 25 03:01:04 PDT 2024
================
@@ -8,13 +8,198 @@
#include "src/__support/CPP/optional.h"
#include "src/__support/UInt.h"
+#include "src/__support/integer_literals.h" // parse_unsigned_bigint
#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128
#include "include/llvm-libc-macros/math-macros.h" // HUGE_VALF, HUGE_VALF
#include "test/UnitTest/Test.h"
namespace LIBC_NAMESPACE {
+enum Value { ZERO, ONE, TWO, MIN, MAX };
+
+template <typename T> auto create(Value value) {
+ switch (value) {
+ case ZERO:
+ return T(0);
+ case ONE:
+ return T(1);
+ case TWO:
+ return T(2);
+ case MIN:
+ return T::min();
+ case MAX:
+ return T::max();
+ }
+}
+
+using Types = testing::TypeList< //
+#ifdef LIBC_TYPES_HAS_INT64
+ BigInt<64, false, uint64_t>, // 64-bits unsigned (1 x uint64_t)
+ BigInt<64, true, uint64_t>, // 64-bits signed (1 x uint64_t)
+#endif
+#ifdef LIBC_TYPES_HAS_INT128
+ BigInt<128, false, __uint128_t>, // 128-bits unsigned (1 x __uint128_t)
+ BigInt<128, true, __uint128_t>, // 128-bits signed (1 x __uint128_t)
+#endif
+ BigInt<16, false, uint16_t>, // 16-bits unsigned (1 x uint16_t)
+ BigInt<16, true, uint16_t>, // 16-bits signed (1 x uint16_t)
+ BigInt<64, false, uint16_t>, // 64-bits unsigned (4 x uint16_t)
+ BigInt<64, true, uint16_t> // 64-bits signed (4 x uint16_t)
+ >;
+
+#define ASSERT_SAME(A, B) ASSERT_TRUE((A) == (B))
+
+TYPED_TEST(LlvmLibcUIntClassTest, Additions, Types) {
+ ASSERT_SAME(create<T>(ZERO) + create<T>(ZERO), create<T>(ZERO));
+ ASSERT_SAME(create<T>(ONE) + create<T>(ZERO), create<T>(ONE));
+ ASSERT_SAME(create<T>(ZERO) + create<T>(ONE), create<T>(ONE));
+ ASSERT_SAME(create<T>(ONE) + create<T>(ONE), create<T>(TWO));
+ // 2's complement addition works for signed and unsigned types.
+ // - unsigned : 0xff + 0x01 = 0x00 (255 + 1 = 0)
+ // - signed : 0xef + 0x01 = 0xf0 (127 + 1 = -128)
+ ASSERT_SAME(create<T>(MAX) + create<T>(ONE), create<T>(MIN));
+}
+
+TYPED_TEST(LlvmLibcUIntClassTest, Subtraction, Types) {
+ ASSERT_SAME(create<T>(ZERO) - create<T>(ZERO), create<T>(ZERO));
+ ASSERT_SAME(create<T>(ONE) - create<T>(ONE), create<T>(ZERO));
+ ASSERT_SAME(create<T>(ONE) - create<T>(ZERO), create<T>(ONE));
+ // 2's complement subtraction works for signed and unsigned types.
+ // - unsigned : 0x00 - 0x01 = 0xff ( 0 - 1 = 255)
+ // - signed : 0xf0 - 0x01 = 0xef (-128 - 1 = 127)
+ ASSERT_SAME(create<T>(MIN) - create<T>(ONE), create<T>(MAX));
+}
+
+TYPED_TEST(LlvmLibcUIntClassTest, Multiplication, Types) {
+ ASSERT_SAME(create<T>(ZERO) * create<T>(ZERO), create<T>(ZERO));
+ ASSERT_SAME(create<T>(ZERO) * create<T>(ONE), create<T>(ZERO));
+ ASSERT_SAME(create<T>(ONE) * create<T>(ZERO), create<T>(ZERO));
+ ASSERT_SAME(create<T>(ONE) * create<T>(ONE), create<T>(ONE));
+ ASSERT_SAME(create<T>(ONE) * create<T>(TWO), create<T>(TWO));
+ ASSERT_SAME(create<T>(TWO) * create<T>(ONE), create<T>(TWO));
+ // - unsigned : 0xff x 0xff = 0x01 (mod 0xff)
+ // - signed : 0xef x 0xef = 0x01 (mod 0xff)
+ ASSERT_SAME(create<T>(MAX) * create<T>(MAX), create<T>(ONE));
+}
+
+template <typename T> void print(const char *msg, T value) {
+ testing::tlog << msg;
+ IntegerToString<T, radix::Hex> buffer(value);
+ testing::tlog << buffer.view() << "\n";
+}
+
+TEST(LlvmLibcUIntClassTest, SignedAddSub) {
+ // Computations performed by https://www.wolframalpha.com/
+ using T = BigInt<128, true, uint32_t>;
+ const T a = parse_bigint<T>("1927508279017230597");
+ const T b = parse_bigint<T>("278789278723478925");
+ const T s = parse_bigint<T>("2206297557740709522");
+ // Addition
+ ASSERT_SAME(a + b, s);
+ ASSERT_SAME(b + a, s); // commutative
+ // Subtraction
+ ASSERT_SAME(a - s, -b);
+ ASSERT_SAME(s - a, b);
+}
+
+TEST(LlvmLibcUIntClassTest, SignedMulDiv) {
+ // Computations performed by https://www.wolframalpha.com/
+ using T = BigInt<128, true, uint16_t>;
+ struct {
+ const char *a;
+ const char *b;
+ const char *mul;
+ } const test_cases[] = {{"-4", "3", "-12"},
----------------
gchatelet wrote:
Done in [c24e4b1](https://github.com/llvm/llvm-project/pull/86137/commits/c24e4b12348a5e775e094819f99c6e35a2977076). This caught an unimplemented feature (right shift of negative numbers) which is now fixed.
https://github.com/llvm/llvm-project/pull/86137
More information about the llvm-commits
mailing list