diff --git a/include/xrpl/basics/Number.h b/include/xrpl/basics/Number.h index 2911d06110..0604a0ccce 100644 --- a/include/xrpl/basics/Number.h +++ b/include/xrpl/basics/Number.h @@ -32,6 +32,15 @@ class Number; std::string to_string(Number const& amount); +template +constexpr bool +isPowerOfTen(T value) +{ + while (value >= 10 && value % 10 == 0) + value /= 10; + return value == 1; +} + class Number { using rep = std::int64_t; @@ -41,7 +50,9 @@ class Number public: // The range for the mantissa when normalized constexpr static std::int64_t minMantissa = 1'000'000'000'000'000LL; - constexpr static std::int64_t maxMantissa = 9'999'999'999'999'999LL; + static_assert(isPowerOfTen(minMantissa)); + constexpr static std::int64_t maxMantissa = minMantissa * 10 - 1; + static_assert(maxMantissa == 9'999'999'999'999'999LL); // The range for the exponent when normalized constexpr static int minExponent = -32768; @@ -54,8 +65,8 @@ public: explicit constexpr Number() = default; - Number(rep mantissa); - explicit Number(rep mantissa, int exponent); + constexpr Number(rep mantissa); + explicit constexpr Number(rep mantissa, int exponent); explicit constexpr Number(rep mantissa, int exponent, unchecked) noexcept; static Number const zero; @@ -205,7 +216,7 @@ public: private: static thread_local rounding_mode mode_; - void + constexpr void normalize(); constexpr bool isnormal() const noexcept; @@ -218,13 +229,13 @@ inline constexpr Number::Number(rep mantissa, int exponent, unchecked) noexcept { } -inline Number::Number(rep mantissa, int exponent) +inline constexpr Number::Number(rep mantissa, int exponent) : mantissa_{mantissa}, exponent_{exponent} { normalize(); } -inline Number::Number(rep mantissa) : Number{mantissa, 0} +inline constexpr Number::Number(rep mantissa) : Number{mantissa, 0} { } diff --git a/include/xrpl/protocol/STAmount.h b/include/xrpl/protocol/STAmount.h index 796a1fb930..fc1835fe72 100644 --- a/include/xrpl/protocol/STAmount.h +++ b/include/xrpl/protocol/STAmount.h @@ -66,16 +66,18 @@ public: static int const cMaxOffset = 80; // Maximum native value supported by the code - static std::uint64_t const cMinValue = 1'000'000'000'000'000ull; - static std::uint64_t const cMaxValue = 9'999'999'999'999'999ull; - static std::uint64_t const cMaxNative = 9'000'000'000'000'000'000ull; + constexpr static std::uint64_t cMinValue = 1'000'000'000'000'000ull; + static_assert(isPowerOfTen(cMinValue)); + constexpr static std::uint64_t cMaxValue = cMinValue * 10 - 1; + static_assert(cMaxValue == 9'999'999'999'999'999ull); + constexpr static std::uint64_t cMaxNative = 9'000'000'000'000'000'000ull; // Max native value on network. - static std::uint64_t const cMaxNativeN = 100'000'000'000'000'000ull; - static std::uint64_t const cIssuedCurrency = 0x8'000'000'000'000'000ull; - static std::uint64_t const cPositive = 0x4'000'000'000'000'000ull; - static std::uint64_t const cMPToken = 0x2'000'000'000'000'000ull; - static std::uint64_t const cValueMask = ~(cPositive | cMPToken); + constexpr static std::uint64_t cMaxNativeN = 100'000'000'000'000'000ull; + constexpr static std::uint64_t cIssuedCurrency = 0x8'000'000'000'000'000ull; + constexpr static std::uint64_t cPositive = 0x4'000'000'000'000'000ull; + constexpr static std::uint64_t cMPToken = 0x2'000'000'000'000'000ull; + constexpr static std::uint64_t cValueMask = ~(cPositive | cMPToken); static std::uint64_t const uRateOne; diff --git a/src/libxrpl/basics/Number.cpp b/src/libxrpl/basics/Number.cpp index 7c3ea2d3cc..3053d84827 100644 --- a/src/libxrpl/basics/Number.cpp +++ b/src/libxrpl/basics/Number.cpp @@ -243,7 +243,7 @@ Number::Guard::doRound(rep& drops) constexpr Number one{1000000000000000, -15, Number::unchecked{}}; -void +constexpr void Number::normalize() { if (mantissa_ == 0)