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;
97 round() const noexcept;
108 std::
string location);
121 doPush(
unsigned d) noexcept;
151 digits_ |= (d & 0x0000'0000'0000'000FULL) << 60;
158 doPush(
static_cast<unsigned>(d));
164 unsigned const d = (
digits_ & 0xF000'0000'0000'0000) >> 60;
201 if (
digits_ > 0x5000'0000'0000'0000)
203 if (
digits_ < 0x5000'0000'0000'0000)
210template <Un
signedMantissa T>
235template <Un
signedMantissa T>
246 if (r == 1 || (r == 0 && (
mantissa & 1) == 1))
262template <Un
signedMantissa T>
271 if (r == 1 || (r == 0 && (
mantissa & 1) == 1))
288 if (r == 1 || (r == 0 && (drops & 1) == 1))
432 XRPL_ASSERT_PARTS(m <=
maxRep,
"xrpl::doNormalize",
"intermediate mantissa fits in int64");
439 "final mantissa fits in range");
444Number::normalize<uint128_t>(
456Number::normalize<unsigned long long>(
468Number::normalize<unsigned long>(
491 XRPL_ASSERT_PARTS(
isnormal(),
"xrpl::Number::shiftExponent",
"normalized");
492 auto const newExponent =
exponent_ + exponentDelta;
500 XRPL_ASSERT_PARTS(result.isnormal(),
"xrpl::Number::shiftExponent",
"result is normalized");
521 XRPL_ASSERT(
isnormal() && y.
isnormal(),
"xrpl::Number::operator+=(Number) : is normal");
609static inline unsigned
613 auto q = (u >> 1) + (u >> 2);
623 auto r =
static_cast<unsigned>(u - ((q << 3) + (q << 1)));
625 auto c = (r + 6) >> 4;
648 int const xs = xn ? -1 : 1;
653 int const ys = yn ? -1 : 1;
657 auto zm = uint128_t(xm) * uint128_t(ym);
660 bool zn = (zs == -1);
685 "Number::multiplication overflow : exponent is " +
std::to_string(xe));
710 int const ns = (np ? -1 : 1);
715 int const ds = (dp ? -1 : 1);
732 uint128_t
const f = small ? 100'000'000'000'000'000 : 10'000'000'000'000'000'000ULL;
733 XRPL_ASSERT_PARTS(f >=
minMantissa * 10,
"Number::operator/=",
"factor expected size");
736 auto const dmu =
static_cast<uint128_t
>(dm);
741 uint128_t
const correctionFactor = 1'000;
743 auto const numerator = uint128_t(nm) * f;
745 auto zm = numerator / dmu;
746 auto ze = ne - de - (small ? 17 : 19);
747 bool zn = (ns * ds) < 0;
769 auto const remainder = (numerator % dmu);
772 zm *= correctionFactor;
773 auto const correction = remainder * correctionFactor / dmu;
784 XRPL_ASSERT_PARTS(
isnormal(),
"xrpl::Number::operator/=",
"result is normalized");
802 for (; offset < 0; ++offset)
807 for (; offset > 0; --offset)
813 g.
doRound(drops,
"Number::operator rep() rounding overflow");
846 bool const negative = amount.negative_;
864 XRPL_ASSERT(
exponent + 43 > 0,
"xrpl::to_string(Number) : minimum exponent");
866 ptrdiff_t
const pad_prefix = rangeLog + 12;
867 ptrdiff_t
const pad_suffix = rangeLog + 8;
873 val.
append(pad_prefix,
'0');
875 val.
append(pad_suffix,
'0');
877 ptrdiff_t
const offset(
exponent + pad_prefix + rangeLog + 1);
879 auto pre_from(val.
begin());
880 auto const pre_to(val.
begin() + offset);
882 auto const post_from(val.
begin() + offset);
883 auto post_to(val.
end());
888 pre_from += pad_prefix;
890 XRPL_ASSERT(post_to >= post_from,
"xrpl::to_string(Number) : first distance check");
892 pre_from =
std::find_if(pre_from, pre_to, [](
char c) {
return c !=
'0'; });
897 post_to -= pad_suffix;
899 XRPL_ASSERT(post_to >= post_from,
"xrpl::to_string(Number) : second distance check");
904 [](
char c) {
return c !=
'0'; })
913 if (pre_from == pre_to)
919 ret.
append(pre_from, pre_to);
922 if (post_to != post_from)
925 ret.
append(post_from, post_to);
941 auto r =
power(f, n / 2);
963 if (f ==
one || d == 1)
973 if (f < zero && d % 2 == 0)
980 auto const di =
static_cast<int>(d);
981 auto ex = [e = e, di = di]()
983 int const k = (e >= 0 ? e : e - (di - 1)) / di;
984 int const k2 = e - (k * di);
992 XRPL_ASSERT_PARTS(f.
isnormal(),
"xrpl::root(Number, unsigned)",
"f is normalized");
1001 auto const D = (((6 * di + 11) * di + 6) * di) + 1;
1002 auto const a0 = 3 * di * ((2 * di - 3) * di + 1);
1003 auto const a1 = 24 * di * (2 * di - 1);
1004 auto const a2 = -30 * (di - 1) * di;
1021 }
while (r != rm1 && r != rm2);
1025 XRPL_ASSERT_PARTS(result.isnormal(),
"xrpl::root(Number, unsigned)",
"result is normalized");
1047 XRPL_ASSERT_PARTS(f.
isnormal(),
"xrpl::root2(Number)",
"f is normalized");
1052 auto const a1 = 144;
1053 auto const a2 = -60;
1064 r = (r + f / r) /
Number(2);
1065 }
while (r != rm1 && r != rm2);
1069 XRPL_ASSERT_PARTS(result.isnormal(),
"xrpl::root2(Number)",
"result is normalized");
1100 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)
bool is_negative() const noexcept
void doRoundDown(bool &negative, T &mantissa, int &exponent, internalrep const &minMantissa)
int round() const noexcept
void doPush(unsigned d) noexcept
void set_negative() noexcept
void doRound(rep &drops, std::string location) const
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)