[WIP] Checkpoint

This commit is contained in:
Ed Hennis
2025-11-25 00:01:53 -05:00
parent 59e6a8107a
commit 359622981e
5 changed files with 158 additions and 93 deletions

View File

@@ -1,6 +1,8 @@
#ifndef XRPL_BASICS_NUMBER_H_INCLUDED
#define XRPL_BASICS_NUMBER_H_INCLUDED
#include <xrpl/beast/utility/instrumentation.h>
#ifdef _MSC_VER
#include <boost/multiprecision/cpp_int.hpp>
#endif
@@ -41,16 +43,16 @@ isPowerOfTen(T value)
}
#ifdef _MSC_VER
using numberuint128 = boost::multiprecision::uint128_t;
using numberint128 = boost::multiprecision::int128_t;
using numberuint = boost::multiprecision::uint128_t;
using numberint = boost::multiprecision::int128_t;
#else // !defined(_MSC_VER)
using numberuint128 = __uint128_t;
using numberint128 = __int128_t;
using numberuint = __uint128_t;
using numberint = __int128_t;
#endif // !defined(_MSC_VER)
struct MantissaRange
{
using internalrep = numberint128;
using internalrep = numberint;
enum mantissa_scale { small, large };
explicit constexpr MantissaRange(mantissa_scale scale_, internalrep min_)
@@ -69,11 +71,14 @@ struct MantissaRange
class Number
{
using uint128_t = numberuint128;
using int128_t = numberint128;
using uint128_t = numberuint;
using int128_t = numberint;
public:
using rep = std::int64_t;
using internalrep = MantissaRange::internalrep;
private:
internalrep mantissa_{0};
int exponent_{std::numeric_limits<int>::lowest()};
@@ -92,12 +97,9 @@ public:
Number(rep mantissa);
explicit Number(internalrep mantissa, int exponent);
explicit constexpr Number(
internalrep mantissa,
int exponent,
unchecked) noexcept;
explicit constexpr Number(internalrep mantissa, int exponent, unchecked) noexcept;
constexpr internalrep
constexpr rep
mantissa() const noexcept;
constexpr int
exponent() const noexcept;
@@ -125,11 +127,11 @@ public:
Number&
operator/=(Number const& x);
static constexpr Number
static Number
min() noexcept;
static constexpr Number
static Number
max() noexcept;
static constexpr Number
static Number
lowest() noexcept;
/** Conversions to Number are implicit and conversions away from Number
@@ -231,6 +233,15 @@ public:
return os << to_string(x);
}
friend std::string
to_string(Number const& amount);
friend Number
root(Number f, unsigned d);
friend Number
root2(Number f);
// Thread local rounding control. Default is to_nearest
enum rounding_mode { to_nearest, towards_zero, downward, upward };
static rounding_mode
@@ -283,21 +294,24 @@ private:
static thread_local rounding_mode mode_;
// The available ranges for mantissa
constexpr static internalrep maxRep =
std::numeric_limits<std::int64_t>::max();
constexpr static MantissaRange smallRange{
MantissaRange::small,
1'000'000'000'000'000LL};
static_assert(isPowerOfTen(smallRange.min));
static_assert(smallRange.max == 9'999'999'999'999'999LL);
static_assert(smallRange.log == 15);
// maxint64 9,223,372,036,854,775,808
constexpr static MantissaRange largeRange{
MantissaRange::large,
1'000'000'000'000'000'000LL};
static_assert(isPowerOfTen(largeRange.min));
// maxRep 9,223,372,036,854,775,808
static_assert(largeRange.max == internalrep(9'999'999'999'999'999'999ULL));
static_assert(largeRange.log == 18);
static_assert(largeRange.min < std::numeric_limits<std::int64_t>::max());
static_assert(largeRange.max > std::numeric_limits<std::int64_t>::max());
static_assert(largeRange.min < maxRep);
static_assert(largeRange.max > maxRep);
// The range for the mantissa when normalized.
// Use reference_wrapper to avoid making copies, and prevent accidentally
@@ -314,16 +328,13 @@ private:
internalrep const& minMantissa,
internalrep const& maxMantissa);
constexpr bool
bool
isnormal() const noexcept;
class Guard;
};
inline constexpr Number::Number(
internalrep mantissa,
int exponent,
unchecked) noexcept
inline constexpr Number::Number(internalrep mantissa, int exponent, unchecked) noexcept
: mantissa_{mantissa}, exponent_{exponent}
{
}
@@ -338,15 +349,34 @@ inline Number::Number(rep mantissa) : Number{mantissa, 0}
{
}
inline constexpr Number::internalrep
inline
constexpr Number::rep
Number::mantissa() const noexcept
{
return mantissa_;
auto m = mantissa_;
if (m > maxRep)
{
XRPL_ASSERT_PARTS(
m % 10 == 0,
"ripple::Number::mantissa",
"large mantissa has no remainder");
m /= 10;
}
return static_cast<Number::rep>(m);
}
inline constexpr int
inline
constexpr int
Number::exponent() const noexcept
{
if (mantissa_ > maxRep)
{
XRPL_ASSERT_PARTS(
mantissa_ % 10 == 0,
"ripple::Number::exponent",
"large mantissa has no remainder");
return exponent_ + 1;
}
return exponent_;
}
@@ -432,25 +462,25 @@ operator/(Number const& x, Number const& y)
return z;
}
inline constexpr Number
inline Number
Number::min() noexcept
{
return Number{range_.get().min, minExponent, unchecked{}};
}
inline constexpr Number
inline Number
Number::max() noexcept
{
return Number{range_.get().max, maxExponent, unchecked{}};
}
inline constexpr Number
inline Number
Number::lowest() noexcept
{
return -Number{range_.get().max, maxExponent, unchecked{}};
}
inline constexpr bool
inline bool
Number::isnormal() const noexcept
{
MantissaRange const& range = range_;