1#include <xrpl/basics/Number.h>
3#include <xrpl/basics/contract.h>
4#include <xrpl/beast/utility/instrumentation.h>
18#pragma message("Using boost::multiprecision::uint128_t and int128_t")
19#include <boost/multiprecision/cpp_int.hpp>
20using uint128_t = boost::multiprecision::uint128_t;
21using int128_t = boost::multiprecision::int128_t;
23using uint128_t = __uint128_t;
24using int128_t = __int128_t;
110 std::
string location);
123 doPush(
unsigned d) noexcept;
153 digits_ |= (d & 0x0000'0000'0000'000FULL) << 60;
160 doPush(
static_cast<unsigned>(d));
166 unsigned d = (
digits_ & 0xF000'0000'0000'0000) >> 60;
203 if (
digits_ > 0x5000'0000'0000'0000)
205 if (
digits_ < 0x5000'0000'0000'0000)
212template <Un
signedMantissa T>
237template <Un
signedMantissa T>
248 if (r == 1 || (r == 0 && (
mantissa & 1) == 1))
264template <Un
signedMantissa T>
273 if (r == 1 || (r == 0 && (
mantissa & 1) == 1))
290 if (r == 1 || (r == 0 && (drops & 1) == 1))
434 XRPL_ASSERT_PARTS(m <=
maxRep,
"xrpl::doNormalize",
"intermediate mantissa fits in int64");
441 "final mantissa fits in range");
446Number::normalize<uint128_t>(
458Number::normalize<unsigned long long>(
470Number::normalize<unsigned long>(
493 XRPL_ASSERT_PARTS(
isnormal(),
"xrpl::Number::shiftExponent",
"normalized");
494 auto const newExponent =
exponent_ + exponentDelta;
502 XRPL_ASSERT_PARTS(result.isnormal(),
"xrpl::Number::shiftExponent",
"result is normalized");
523 XRPL_ASSERT(
isnormal() && y.
isnormal(),
"xrpl::Number::operator+=(Number) : is normal");
611static inline unsigned
615 auto q = (u >> 1) + (u >> 2);
625 auto r =
static_cast<unsigned>(u - ((q << 3) + (q << 1)));
627 auto c = (r + 6) >> 4;
650 int xs = xn ? -1 : 1;
655 int ys = yn ? -1 : 1;
659 auto zm = uint128_t(xm) * uint128_t(ym);
662 bool zn = (zs == -1);
687 "Number::multiplication overflow : exponent is " +
std::to_string(xe));
712 int ns = (np ? -1 : 1);
717 int ds = (dp ? -1 : 1);
734 uint128_t
const f = small ? 100'000'000'000'000'000 : 10'000'000'000'000'000'000ULL;
735 XRPL_ASSERT_PARTS(f >=
minMantissa * 10,
"Number::operator/=",
"factor expected size");
738 auto const dmu =
static_cast<uint128_t
>(dm);
743 uint128_t
const correctionFactor = 1'000;
745 auto const numerator = uint128_t(nm) * f;
747 auto zm = numerator / dmu;
748 auto ze = ne - de - (small ? 17 : 19);
749 bool zn = (ns * ds) < 0;
771 auto const remainder = (numerator % dmu);
774 zm *= correctionFactor;
775 auto const correction = remainder * correctionFactor / dmu;
786 XRPL_ASSERT_PARTS(
isnormal(),
"xrpl::Number::operator/=",
"result is normalized");
804 for (; offset < 0; ++offset)
809 for (; offset > 0; --offset)
815 g.
doRound(drops,
"Number::operator rep() rounding overflow");
848 bool const negative = amount.negative_;
866 XRPL_ASSERT(
exponent + 43 > 0,
"xrpl::to_string(Number) : minimum exponent");
868 ptrdiff_t
const pad_prefix = rangeLog + 12;
869 ptrdiff_t
const pad_suffix = rangeLog + 8;
875 val.
append(pad_prefix,
'0');
877 val.
append(pad_suffix,
'0');
879 ptrdiff_t
const offset(
exponent + pad_prefix + rangeLog + 1);
881 auto pre_from(val.
begin());
882 auto const pre_to(val.
begin() + offset);
884 auto const post_from(val.
begin() + offset);
885 auto post_to(val.
end());
890 pre_from += pad_prefix;
892 XRPL_ASSERT(post_to >= post_from,
"xrpl::to_string(Number) : first distance check");
894 pre_from =
std::find_if(pre_from, pre_to, [](
char c) {
return c !=
'0'; });
899 post_to -= pad_suffix;
901 XRPL_ASSERT(post_to >= post_from,
"xrpl::to_string(Number) : second distance check");
906 [](
char c) {
return c !=
'0'; })
915 if (pre_from == pre_to)
918 ret.
append(pre_from, pre_to);
920 if (post_to != post_from)
923 ret.
append(post_from, post_to);
939 auto r =
power(f, n / 2);
961 if (f ==
one || d == 1)
971 if (f < zero && d % 2 == 0)
978 auto const di =
static_cast<int>(d);
979 auto ex = [e = e, di = di]()
981 int k = (e >= 0 ? e : e - (di - 1)) / di;
990 XRPL_ASSERT_PARTS(f.
isnormal(),
"xrpl::root(Number, unsigned)",
"f is normalized");
999 auto const D = ((6 * di + 11) * di + 6) * di + 1;
1000 auto const a0 = 3 * di * ((2 * di - 3) * di + 1);
1001 auto const a1 = 24 * di * (2 * di - 1);
1002 auto const a2 = -30 * (di - 1) * di;
1019 }
while (r != rm1 && r != rm2);
1023 XRPL_ASSERT_PARTS(result.isnormal(),
"xrpl::root(Number, unsigned)",
"result is normalized");
1045 XRPL_ASSERT_PARTS(f.
isnormal(),
"xrpl::root2(Number)",
"f is normalized");
1050 auto const a1 = 144;
1051 auto const a2 = -60;
1062 r = (r + f / r) /
Number(2);
1063 }
while (r != rm1 && r != rm2);
1067 XRPL_ASSERT_PARTS(result.isnormal(),
"xrpl::root2(Number)",
"result is normalized");
1098 if ((n % 2) == 1 && (d % 2) == 0 && f < zero)
void set_positive() noexcept
void doRoundUp(bool &negative, T &mantissa, int &exponent, internalrep const &minMantissa, internalrep const &maxMantissa, std::string location)
void bringIntoRange(bool &negative, T &mantissa, int &exponent, internalrep const &minMantissa)
void doRound(rep &drops, std::string location)
bool is_negative() const noexcept
void doRoundDown(bool &negative, T &mantissa, int &exponent, internalrep const &minMantissa)
void doPush(unsigned d) noexcept
void set_negative() noexcept
Number is a floating point type that can represent a wide range of values.
static constexpr Number oneSmall()
oneSmall is needed because the ranges are private
static rounding_mode getround()
static internalrep minMantissa()
constexpr rep mantissa() const noexcept
Returns the mantissa of the external view of the Number.
static rounding_mode setround(rounding_mode mode)
Number & operator/=(Number const &x)
Number & operator+=(Number const &x)
Number truncate() const noexcept
friend std::string to_string(Number const &amount)
static constexpr MantissaRange smallRange
friend void doNormalize(bool &negative, T &mantissa_, int &exponent_, MantissaRange::rep const &minMantissa, MantissaRange::rep const &maxMantissa)
static constexpr internalrep maxRep
MantissaRange::rep internalrep
static thread_local rounding_mode mode_
static constexpr int minExponent
Number shiftExponent(int exponentDelta) const
static void setMantissaScale(MantissaRange::mantissa_scale scale)
Changes which mantissa scale is used for normalization.
static internalrep externalToInternal(rep mantissa)
static internalrep maxMantissa()
bool isnormal() const noexcept
constexpr int exponent() const noexcept
Returns the exponent of the external view of the Number.
static constexpr int maxExponent
static thread_local std::reference_wrapper< MantissaRange const > range_
friend Number root2(Number f)
static MantissaRange::mantissa_scale getMantissaScale()
Returns which mantissa scale is currently in use for normalization.
static constexpr MantissaRange largeRange
Number & operator*=(Number const &x)
constexpr Number()=default
static constexpr Number oneLarge()
oneLarge is needed because the ranges are private
friend Number root(Number f, unsigned d)
T make_reverse_iterator(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
ClosedInterval< T > range(T low, T high)
Create a closed range interval.
Number power(Number const &f, unsigned n)
constexpr Number abs(Number x) noexcept
static unsigned divu10(uint128_t &u)