diff --git a/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp b/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp index 0abf836ec24..0294976ed45 100644 --- a/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp +++ b/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp @@ -147,6 +147,20 @@ ErrorOr UnsignedBigInteger::to_base(u16 N) const return StringView(buffer.bytes().slice(0, written - 1)).to_ascii_lowercase_string(); } +size_t UnsignedBigInteger::count_digits_in_base(u16 base) const +{ + VERIFY(base <= 36); + + if (is_zero()) + return 1; + + int size = 0; + MP_MUST(mp_radix_size(&m_mp, base, &size)); + + // mp_radix_size includes a null byte. + return static_cast(size) - 1; +} + u64 UnsignedBigInteger::to_u64() const { return mp_get_u64(&m_mp); diff --git a/Libraries/LibCrypto/BigInt/UnsignedBigInteger.h b/Libraries/LibCrypto/BigInt/UnsignedBigInteger.h index bb7ac6862f4..53900083b1f 100644 --- a/Libraries/LibCrypto/BigInt/UnsignedBigInteger.h +++ b/Libraries/LibCrypto/BigInt/UnsignedBigInteger.h @@ -47,6 +47,8 @@ public: [[nodiscard]] static ErrorOr from_base(u16 N, StringView str); [[nodiscard]] ErrorOr to_base(u16 N) const; + [[nodiscard]] size_t count_digits_in_base(u16 base) const; + [[nodiscard]] u64 to_u64() const; enum class RoundingMode { diff --git a/Tests/LibCrypto/TestBigInteger.cpp b/Tests/LibCrypto/TestBigInteger.cpp index 61c5abd4e0e..8ff95c56cfe 100644 --- a/Tests/LibCrypto/TestBigInteger.cpp +++ b/Tests/LibCrypto/TestBigInteger.cpp @@ -209,6 +209,31 @@ TEST_CASE(test_unsigned_bigint_base10_to_string) EXPECT_EQ(result, "57195071295721390579057195715793"); } +TEST_CASE(test_unsigned_bigint_count_digits) +{ + constexpr auto count_digits = [](u64 number, u16 base) { + u8 digits = 0; + + do { + number /= base; + ++digits; + } while (number > 0); + + return digits; + }; + + for (auto base : to_array({ 2, 8, 10, 16 })) { + for (auto test : to_array({ 0, 9, 10, 19, 99, 100, 999, 1000, 9999, 10000, 99999, 10000000000, 99999999999 })) { + auto bigint = Crypto::UnsignedBigInteger { test }; + + auto result = bigint.count_digits_in_base(base); + auto expected = count_digits(test, base); + + EXPECT_EQ(result, expected); + } + } +} + static size_t count_leading_zeros(Bytes data) { auto leading_zeros = 0u;