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;
112 std::
string location);
129 doPush(
unsigned d) noexcept;
163 digits_ |= (d & 0x0000'0000'0000'000FULL) << 60;
170 doPush(
static_cast<unsigned>(d));
176 unsigned d = (
digits_ & 0xF000'0000'0000'0000) >> 60;
213 if (
digits_ > 0x5000'0000'0000'0000)
215 if (
digits_ < 0x5000'0000'0000'0000)
222template <Un
signedMantissa T>
247template <Un
signedMantissa T>
258 if (r == 1 || (r == 0 && (
mantissa & 1) == 1))
274template <Un
signedMantissa T>
283 if (r == 1 || (r == 0 && (
mantissa & 1) == 1))
300 if (r == 1 || (r == 0 && (drops & 1) == 1))
455 "intermediate mantissa fits in int64");
464 "Number::normalize 2");
468 "final mantissa fits in range");
473Number::normalize<uint128_t>(
485Number::normalize<unsigned long long>(
497Number::normalize<unsigned long>(
520 XRPL_ASSERT_PARTS(
isnormal(),
"xrpl::Number::shiftExponent",
"normalized");
521 auto const newExponent =
exponent_ + exponentDelta;
531 "xrpl::Number::shiftExponent",
532 "result is normalized");
555 "xrpl::Number::operator+=(Number) : is normal");
644static inline unsigned
648 auto q = (u >> 1) + (u >> 2);
658 auto r =
static_cast<unsigned>(u - ((q << 3) + (q << 1)));
660 auto c = (r + 6) >> 4;
683 int xs = xn ? -1 : 1;
688 int ys = yn ? -1 : 1;
692 auto zm = uint128_t(xm) * uint128_t(ym);
695 bool zn = (zs == -1);
720 "Number::multiplication overflow : exponent is " +
std::to_string(xe));
745 int ns = (np ? -1 : 1);
750 int ds = (dp ? -1 : 1);
768 small ? 100'000'000'000'000'000 : 10'000'000'000'000'000'000ULL;
770 f >=
minMantissa * 10,
"Number::operator/=",
"factor expected size");
773 auto const dmu =
static_cast<uint128_t
>(dm);
778 uint128_t
const correctionFactor = 1'000;
780 auto const numerator = uint128_t(nm) * f;
782 auto zm = numerator / dmu;
783 auto ze = ne - de - (small ? 17 : 19);
784 bool zn = (ns * ds) < 0;
806 auto const remainder = (numerator % dmu);
809 zm *= correctionFactor;
810 auto const correction = remainder * correctionFactor / dmu;
822 isnormal(),
"xrpl::Number::operator/=",
"result is normalized");
827Number::operator
rep()
const
839 for (; offset < 0; ++offset)
844 for (; offset > 0; --offset)
850 g.
doRound(drops,
"Number::operator rep() rounding overflow");
883 bool const negative = amount.negative_;
904 exponent + 43 > 0,
"xrpl::to_string(Number) : minimum exponent");
906 ptrdiff_t
const pad_prefix = rangeLog + 12;
907 ptrdiff_t
const pad_suffix = rangeLog + 8;
913 val.
append(pad_prefix,
'0');
915 val.
append(pad_suffix,
'0');
917 ptrdiff_t
const offset(
exponent + pad_prefix + rangeLog + 1);
919 auto pre_from(val.
begin());
920 auto const pre_to(val.
begin() + offset);
922 auto const post_from(val.
begin() + offset);
923 auto post_to(val.
end());
928 pre_from += pad_prefix;
931 post_to >= post_from,
"xrpl::to_string(Number) : first distance check");
933 pre_from =
std::find_if(pre_from, pre_to, [](
char c) {
return c !=
'0'; });
938 post_to -= pad_suffix;
941 post_to >= post_from,
942 "xrpl::to_string(Number) : second distance check");
947 [](
char c) {
return c !=
'0'; })
956 if (pre_from == pre_to)
959 ret.
append(pre_from, pre_to);
961 if (post_to != post_from)
964 ret.
append(post_from, post_to);
980 auto r =
power(f, n / 2);
1002 if (f ==
one || d == 1)
1012 if (f < zero && d % 2 == 0)
1019 auto const di =
static_cast<int>(d);
1020 auto ex = [e = e, di = di]()
1022 int k = (e >= 0 ? e : e - (di - 1)) / di;
1023 int k2 = e - k * di;
1032 f.
isnormal(),
"xrpl::root(Number, unsigned)",
"f is normalized");
1041 auto const D = ((6 * di + 11) * di + 6) * di + 1;
1042 auto const a0 = 3 * di * ((2 * di - 3) * di + 1);
1043 auto const a1 = 24 * di * (2 * di - 1);
1044 auto const a2 = -30 * (di - 1) * di;
1061 }
while (r != rm1 && r != rm2);
1067 "xrpl::root(Number, unsigned)",
1068 "result is normalized");
1090 XRPL_ASSERT_PARTS(f.
isnormal(),
"xrpl::root2(Number)",
"f is normalized");
1095 auto const a1 = 144;
1096 auto const a2 = -60;
1107 r = (r + f / r) /
Number(2);
1108 }
while (r != rm1 && r != rm2);
1113 result.isnormal(),
"xrpl::root2(Number)",
"result is normalized");
1144 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)