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>
233template <Un
signedMantissa T>
244 if (r == 1 || (r == 0 && (
mantissa & 1) == 1))
260template <Un
signedMantissa T>
265 if (r == 1 || (r == 0 && (
mantissa & 1) == 1))
282 if (r == 1 || (r == 0 && (drops & 1) == 1))
426 XRPL_ASSERT_PARTS(m <=
maxRep,
"xrpl::doNormalize",
"intermediate mantissa fits in int64");
436Number::normalize<uint128_t>(
448Number::normalize<unsigned long long>(
460Number::normalize<unsigned long>(
483 XRPL_ASSERT_PARTS(
isnormal(),
"xrpl::Number::shiftExponent",
"normalized");
484 auto const newExponent =
exponent_ + exponentDelta;
492 XRPL_ASSERT_PARTS(result.isnormal(),
"xrpl::Number::shiftExponent",
"result is normalized");
513 XRPL_ASSERT(
isnormal() && y.
isnormal(),
"xrpl::Number::operator+=(Number) : is normal");
601static inline unsigned
605 auto q = (u >> 1) + (u >> 2);
615 auto r =
static_cast<unsigned>(u - ((q << 3) + (q << 1)));
617 auto c = (r + 6) >> 4;
640 int xs = xn ? -1 : 1;
645 int ys = yn ? -1 : 1;
649 auto zm = uint128_t(xm) * uint128_t(ym);
652 bool zn = (zs == -1);
697 int ns = (np ? -1 : 1);
702 int ds = (dp ? -1 : 1);
719 uint128_t
const f = small ? 100'000'000'000'000'000 : 10'000'000'000'000'000'000ULL;
720 XRPL_ASSERT_PARTS(f >=
minMantissa * 10,
"Number::operator/=",
"factor expected size");
723 auto const dmu =
static_cast<uint128_t
>(dm);
728 uint128_t
const correctionFactor = 1'000;
730 auto const numerator = uint128_t(nm) * f;
732 auto zm = numerator / dmu;
733 auto ze = ne - de - (small ? 17 : 19);
734 bool zn = (ns * ds) < 0;
756 auto const remainder = (numerator % dmu);
759 zm *= correctionFactor;
760 auto const correction = remainder * correctionFactor / dmu;
771 XRPL_ASSERT_PARTS(
isnormal(),
"xrpl::Number::operator/=",
"result is normalized");
789 for (; offset < 0; ++offset)
794 for (; offset > 0; --offset)
800 g.
doRound(drops,
"Number::operator rep() rounding overflow");
833 bool const negative = amount.negative_;
851 XRPL_ASSERT(
exponent + 43 > 0,
"xrpl::to_string(Number) : minimum exponent");
853 ptrdiff_t
const pad_prefix = rangeLog + 12;
854 ptrdiff_t
const pad_suffix = rangeLog + 8;
860 val.
append(pad_prefix,
'0');
862 val.
append(pad_suffix,
'0');
864 ptrdiff_t
const offset(
exponent + pad_prefix + rangeLog + 1);
866 auto pre_from(val.
begin());
867 auto const pre_to(val.
begin() + offset);
869 auto const post_from(val.
begin() + offset);
870 auto post_to(val.
end());
875 pre_from += pad_prefix;
877 XRPL_ASSERT(post_to >= post_from,
"xrpl::to_string(Number) : first distance check");
879 pre_from =
std::find_if(pre_from, pre_to, [](
char c) {
return c !=
'0'; });
884 post_to -= pad_suffix;
886 XRPL_ASSERT(post_to >= post_from,
"xrpl::to_string(Number) : second distance check");
898 if (pre_from == pre_to)
901 ret.
append(pre_from, pre_to);
903 if (post_to != post_from)
906 ret.
append(post_from, post_to);
922 auto r =
power(f, n / 2);
944 if (f ==
one || d == 1)
954 if (f < zero && d % 2 == 0)
961 auto const di =
static_cast<int>(d);
962 auto ex = [e = e, di = di]()
964 int k = (e >= 0 ? e : e - (di - 1)) / di;
973 XRPL_ASSERT_PARTS(f.
isnormal(),
"xrpl::root(Number, unsigned)",
"f is normalized");
982 auto const D = ((6 * di + 11) * di + 6) * di + 1;
983 auto const a0 = 3 * di * ((2 * di - 3) * di + 1);
984 auto const a1 = 24 * di * (2 * di - 1);
985 auto const a2 = -30 * (di - 1) * di;
1002 }
while (r != rm1 && r != rm2);
1006 XRPL_ASSERT_PARTS(result.isnormal(),
"xrpl::root(Number, unsigned)",
"result is normalized");
1028 XRPL_ASSERT_PARTS(f.
isnormal(),
"xrpl::root2(Number)",
"f is normalized");
1033 auto const a1 = 144;
1034 auto const a2 = -60;
1045 r = (r + f / r) /
Number(2);
1046 }
while (r != rm1 && r != rm2);
1050 XRPL_ASSERT_PARTS(result.isnormal(),
"xrpl::root2(Number)",
"result is normalized");
1081 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)