xrpld
Loading...
Searching...
No Matches
libxrpl/basics/Number.cpp
1#include <xrpl/basics/Number.h>
2
3#include <xrpl/basics/contract.h>
4#include <xrpl/beast/utility/instrumentation.h>
5
6#include <algorithm>
7#include <cstddef>
8#include <cstdint>
9#include <functional>
10#include <iterator>
11#include <limits>
12#include <numeric>
13#include <set>
14#include <stdexcept>
15#include <string>
16#include <type_traits>
17#include <utility>
18
19#ifdef _MSC_VER
20#pragma message("Using boost::multiprecision::uint128_t and int128_t")
21#include <boost/multiprecision/cpp_int.hpp>
22using UInt128T = boost::multiprecision::uint128_t;
23using Int128T = boost::multiprecision::int128_t;
24#else // !defined(_MSC_VER)
25using UInt128T = __uint128_t;
26using Int128T = __int128_t;
27#endif // !defined(_MSC_VER)
28
29namespace xrpl {
30
32thread_local std::reference_wrapper<MantissaRange const> Number::kRange =
34
35std::string
37{
38 switch (scale)
39 {
41 return "Small";
43 return "LargeLegacy";
45 return "Large320";
47 return "Large330";
48 default:
49 throw std::runtime_error("Bad scale"); // LCOV_EXCL_LINE
50 }
51}
52
55{
56 switch (round)
57 {
59 return "ToNearest";
61 return "TowardsZero";
63 return "Downward";
65 return "Upward";
66 default:
67 throw std::runtime_error("Bad rounding mode"); // LCOV_EXCL_LINE
68 }
69}
70
71constexpr MantissaRange const&
73{
74 static constexpr MantissaRange kSmall{MantissaScale::Small};
75 static constexpr MantissaRange kLegacy{MantissaScale::LargeLegacy};
76 static constexpr MantissaRange kLarge320{MantissaScale::Large320};
77 static constexpr MantissaRange kLarge330{MantissaScale::Large330};
78
79 switch (scale)
80 {
82 return kSmall;
84 return kLegacy;
86 return kLarge320;
88 return kLarge330;
89 }
90 throw std::logic_error("Unknown mantissa scale");
91
92 // static_asserts are checked at compile time, so it doesn't matter where in the function they
93 // are located. For readability of the main body, put them after it.
94
95 // Small
96 static_assert(isPowerOfTen(kSmall.min));
97 static_assert(kSmall.min == 1'000'000'000'000'000LL);
98 static_assert(kSmall.max == 9'999'999'999'999'999LL);
99 static_assert(kSmall.log == 15);
100 static_assert(kSmall.min < Number::kMaxRep);
101 static_assert(kSmall.max < Number::kMaxRep);
102 static_assert(kSmall.cuspRoundingFix == CuspRoundingFix::Disabled);
103
104 // LargeLegacy
105 static_assert(isPowerOfTen(kLegacy.min));
106 static_assert(kLegacy.min == 1'000'000'000'000'000'000ULL);
107 static_assert(kLegacy.max == rep(9'999'999'999'999'999'999ULL));
108 static_assert(kLegacy.log == 18);
109 static_assert(kLegacy.min < Number::kMaxRep);
110 static_assert(kLegacy.max > Number::kMaxRep);
111 static_assert(kLegacy.cuspRoundingFix == CuspRoundingFix::Disabled);
112
113 // Large320
114 static_assert(isPowerOfTen(kLarge320.min));
115 static_assert(kLarge320.min == 1'000'000'000'000'000'000ULL);
116 static_assert(kLarge320.max == rep(9'999'999'999'999'999'999ULL));
117 static_assert(kLarge320.log == 18);
118 static_assert(kLarge320.min < Number::kMaxRep);
119 static_assert(kLarge320.max > Number::kMaxRep);
120 static_assert(kLarge320.cuspRoundingFix == CuspRoundingFix::Enabled320);
121
122 // Large330
123 static_assert(isPowerOfTen(kLarge330.min));
124 static_assert(kLarge330.min == 1'000'000'000'000'000'000ULL);
125 static_assert(kLarge330.max == rep(9'999'999'999'999'999'999ULL));
126 static_assert(kLarge330.log == 18);
127 static_assert(kLarge330.min < Number::kMaxRep);
128 static_assert(kLarge330.max > Number::kMaxRep);
129 static_assert(kLarge330.cuspRoundingFix == CuspRoundingFix::Enabled330);
130}
131
134{
135 return mode;
136}
137
140{
141 return std::exchange(Number::mode, inMode);
142}
143
146{
147 return kRange.get().scale;
148}
149
150void
157
158// Optimization equivalent to:
159// auto r = static_cast<unsigned>(u % 10);
160// u /= 10;
161// return r;
162// Derived from Hacker's Delight Second Edition Chapter 10
163// by Henry S. Warren, Jr.
164static inline unsigned
165divu10(UInt128T& u)
166{
167 // q = u * 0.75
168 auto q = (u >> 1) + (u >> 2);
169 // iterate towards q = u * 0.8
170 q += q >> 4;
171 q += q >> 8;
172 q += q >> 16;
173 q += q >> 32;
174 q += q >> 64;
175 // q /= 8 approximately == u / 10
176 q >>= 3;
177 // r = u - q * 10 approximately == u % 10
178 auto r = static_cast<unsigned>(u - ((q << 3) + (q << 1)));
179 // correction c is 1 if r >= 10 else 0
180 auto c = (r + 6) >> 4;
181 u = q + c;
182 r -= c * 10;
183 return r;
184}
185
186template <class T>
188
220{
221 std::uint64_t digits_{0}; // 16 decimal guard digits
222 std::uint8_t xbit_ : 1 {0}; // has a non-zero digit been shifted off the end
223 std::uint8_t sbit_ : 1 {0}; // the sign of the guard digits
224
225public:
229
237
241
242 // set & test the sign bit
243 void
244 setPositive() noexcept;
245 void
246 setNegative() noexcept;
247 // Should only be called by doNormalize, and then only for division
248 // operations with remainders.
249 void
250 setDropped() noexcept;
251 [[nodiscard]] bool
252 isNegative() const noexcept;
253
254 // add a digit
255 template <class T>
256 void
257 push(T d) noexcept;
258
259 // recover a digit
260 unsigned
261 pop() noexcept;
262
263 // if true, there are no recoverable digits in the guard, though there may be dropped digits
264 // (xbit_)
265 [[nodiscard]] bool
266 unrecoverable() const noexcept;
267
268 // if true, there are no digits in the guard, including dropped digits (xbit_)
269 [[nodiscard]] bool
270 empty() const noexcept;
271
281 template <class T>
282 void
283 doDropDigit(T& mantissa, int& exponent) noexcept;
284
292 template <class T>
293 void
294 doDropDigitWithTarget(T& mantissa, int& exponent, int const targetExponent) noexcept;
295
296 // Modify the result to the correctly rounded value
297 template <UnsignedMantissa T>
298 void
299 doRoundUp(bool& negative, T& mantissa, int& exponent, std::string location);
300
301 // Modify the result to the correctly rounded value
302 template <UnsignedMantissa T>
303 void
304 doRoundDown(bool& negative, T& mantissa, int& exponent) const;
305
306 // Modify the result to the correctly rounded value
307 void
308 doRound(rep& drops, std::string location) const;
309
310private:
311 template <UnsignedMantissa T>
312 void
313 pushOverflow(T mantissa);
314
315 enum class Round {
316 // The result is exact. No rounding is needed. Only used if cuspRoundingFix is Enabled330 or
317 // higher.
318 Exact = -2,
319 // Round down. Since we use integer math, that usually means no change is needed.
320 // Exceptions are for when the result is between kMaxRep and kMaxRepUp (round to kMaxRep),
321 // or after subtraction where _any_ remainder will modify the result. The latter is what
322 // distinguishes Exact from Down.
323 Down = -1,
324 // The result was exactly half-way between two integers. This will round to even.
325 Even = 0,
326 // Round up. Always adds 1 (or subtracts 1 in some cases if cuspRoundingFix is not
327 // Enabled330)
328 Up = 1,
329 };
330
331 // Indicate round direction. See Round enum above.
332 // This enables the client to round towards nearest, and on
333 // tie, round towards even.
334 [[nodiscard]] Round
335 round() const noexcept;
336
337 void
338 doPush(unsigned d) noexcept;
339
340 template <UnsignedMantissa T>
341 void
342 bringIntoRange(bool& negative, T& mantissa, int& exponent) const;
343};
344
345inline void
347{
348 sbit_ = 0;
349}
350
351inline void
353{
354 sbit_ = 1;
355}
356
357inline void
359{
360 xbit_ = 1;
361}
362
363inline bool
365{
366 return sbit_ == 1;
367}
368
369inline void
370Number::Guard::doPush(unsigned d) noexcept
371{
372 XRPL_ASSERT(d < 10, "xrpl::Number::Guard::doPush : valid digit");
373 xbit_ = xbit_ || ((digits_ & 0x0000'0000'0000'000F) != 0);
374 digits_ >>= 4;
375 digits_ |= (d & 0x0000'0000'0000'000FULL) << 60;
376}
377
378template <class T>
379inline void
381{
382 doPush(static_cast<unsigned>(d));
383}
384
385inline unsigned
387{
388 unsigned const d = (digits_ & 0xF000'0000'0000'0000) >> 60;
389 digits_ <<= 4;
390 return d;
391}
392
393inline bool
395{
396 return digits_ == 0;
397}
398
399inline bool
400Number::Guard::empty() const noexcept
401{
402 return unrecoverable() && !xbit_;
403}
404
405template <class T>
406void
408{
409 push(mantissa % 10);
410 mantissa /= 10;
411 ++exponent;
412}
413
414// Use the divu10 optimization for uint128s
415template <>
416void
418{
419 // The following is optimization for:
420 // push(static_cast<unsigned>(mantissa % 10));
421 // mantissa /= 10;
423 ++exponent;
424}
425
426template <class T>
427void
428Number::Guard::doDropDigitWithTarget(T& mantissa, int& exponent, int const targetExponent) noexcept
429{
430 XRPL_ASSERT(
431 exponent < targetExponent, "xrpl::Number::Guard::doDropDigitWithTarget : something to do");
432 while (exponent < targetExponent)
433 {
434 if (mantissa == 0 && unrecoverable())
435 {
436 // No number of dropped digits is going to change anything except the exponent at this
437 // point, so just jump to the result
438 exponent = targetExponent;
439 return;
440 }
442 }
443}
444
445template <UnsignedMantissa T>
446void
448{
449 XRPL_ASSERT(mantissa <= kMaxRepUp, "xrpl::Number::Guard::pushOverflow : valid mantissa");
452 {
453 // Special case rounding rules for the values in the range [kMaxRep, kMaxRepUp).
454
455 auto constexpr spread = kMaxRepUp - kMaxRep;
456 static_assert(spread == 3);
457
458 // Round in two steps.
459
460 // The first step uses the digits _already_ in the Guard to possibly round the mantissa up.
461 // Ultimately, the purpose of this step is to capture rounding where the stored digits would
462 // change the decision without those digits. (e.g. From just _below_ the midpoint to just
463 // _above_ the midpoint for ToNearest, or from kMaxRep into the in-between for Upward. Make
464 // an exception if the final digit is 9, because it can only get larger, and we don't want
465 // to bump up to kMaxRepUp.
466 if (mantissa % 10 < 9)
467 {
468 // Intentionally use integer math to get the largest value under the midpoint.
469 auto constexpr kMidpoint = kMaxRep + (spread / 2);
470 static_assert(kMidpoint == kMaxRep + 1);
471 auto const r = round();
472 if (r == Round::Up || (r == Round::Even && mantissa == kMidpoint))
473 {
474 ++mantissa;
475 }
476 }
477
478 // The second step scales the final digit of the updated mantissa proportionally, converting
479 // from (kMaxRep, kMaxRepUp) to (0 to 9]. It then pushes that scaled digit onto the guard as
480 // if it was a digit that got removed, but doesn't actually remove it. This method should be
481 // future-proof in case the number of mantissa bits ever changes. (Though for integer values
482 // of the form 2^(2^x-1), the spread will always be the same.) Effects:
483 // * For round to nearest
484 // * if the updated mantissa is below the midpoint, it'll round "down" to kMaxRep
485 // * if above the midpoint, it'll round "up" to kMaxRepUp
486 // * it can never be exactly at the midpoint, because kMaxRepUp is always even, and
487 // kMaxRep is always odd, so don't worry about that case.
488 // * For round upward, will round up to kMaxRepUp for positive values, down to kMaxRep for
489 // negative.
490 // * For round downward, does the opposite of upward.
491 // * For round toward zero, always rounds down to kMaxRep.
492
493 auto const diff = mantissa - kMaxRep;
494 auto const digit = static_cast<unsigned>((diff * 10) / spread);
495 XRPL_ASSERT(
496 digit < 10u && digit != 5, "xrpl::Number::Guard::pushOverflow : valid overflow digit");
497
498 // Don't remove the digit from the mantissa, but add it to the guard as if it was.
499 push(digit);
500 }
501}
502
503// Returns:
504// Exact if Guard is _zero_, and appropriate amendments are enabled
505// Down if Guard is less than half
506// Even if Guard is exactly half
507// Up if Guard is greater than half
509Number::Guard::round() const noexcept
510{
511 // Local "mode" shadows and has the same value as the static thread_local "Number::mode".
512 // This ensures the overhead of loading the thread_local is only incurred once.
513 auto const mode = Number::getround();
514
516 {
517 // No remainder
518 return Round::Exact;
519 }
520
522 return Round::Down;
523
524 // Also Towards Zero
526 {
527 return Round::Down;
528 }
529
530 // Away from Zero. Since we checked sbit_ in the previous block, we don't need to check it
531 // again.
533 {
534 if (empty())
535 return Round::Down;
536 return Round::Up;
537 }
538
539 XRPL_ASSERT(
540 mode == RoundingMode::ToNearest, "xrpl::Number::Guard::Round : fallthrough to ToNearest");
541 // assume round to nearest if mode is not one of the predefined values
542 if (digits_ > 0x5000'0000'0000'0000)
543 return Round::Up;
544 if (digits_ < 0x5000'0000'0000'0000)
545 return Round::Down;
546 if (xbit_)
547 return Round::Up;
548 return Round::Even;
549}
550
551template <UnsignedMantissa T>
552void
553Number::Guard::bringIntoRange(bool& negative, T& mantissa, int& exponent) const
554{
555 // Bring mantissa back into the minMantissa / maxMantissa range AFTER
556 // rounding.
557 if (mantissa < minMantissa &&
559 {
560 mantissa *= 10;
561 --exponent;
562 }
563 // mantissa should never be 0, but if it _is_ assert, but fall back to making the result kZero.
564 if (exponent < kMinExponent ||
566 {
567 // Engineers: If you hit this assert, you probably did something wrong in the operation
568 // leading up to the rounding work.
569 XRPL_ASSERT(mantissa != 0, "xrpl::Number::Guard::bringIntoRange : valid mantissa");
570 static constexpr Number kZero = Number{};
571
572 negative = kZero.negative_;
573 mantissa = kZero.mantissa_;
574 exponent = kZero.exponent_;
575 }
576}
577
578template <UnsignedMantissa T>
579void
580Number::Guard::doRoundUp(bool& negative, T& mantissa, int& exponent, std::string location)
581{
583
584 auto const r = round();
585 if (r == Round::Up || (r == Round::Even && (mantissa & 1) == 1))
586 {
587 auto const safeToIncrement = [this](auto const& mantissa) {
588 return mantissa < maxMantissa && mantissa < kMaxRep;
589 };
591 {
592 // Ensure mantissa after incrementing fits within both the
593 // min/maxMantissa range and is a valid "rep".
594 if (safeToIncrement(mantissa))
595 {
596 // Nothing unusual here, just increment the mantissa
597 ++mantissa;
598 }
599 else
600 {
603 {
604 // When rounding up a value in between kMaxRep, and kMaxRepUp, round to
605 // kMaxRepUp. Note that the decision for this rounding is dominated by the
606 // results of pushOverflow.
608 }
609 else
610 {
611 // Incrementing the mantissa will require dividing, which will require rounding.
612 // So _don't_ increment the mantissa. Instead, divide and round recursively. It
613 // should be impossible to recurse more than once, because once the mantissa is
614 // divided by 10, it will be _well_ under maxMantissa and kMaxRep, so adding 1
615 // will have no chance of bringing it back over.
617 XRPL_ASSERT_PARTS(
618 safeToIncrement(mantissa),
619 "xrpl::Number::Guard::doRoundUp",
620 "can't recurse more than once");
621 doRoundUp(negative, mantissa, exponent, location);
622 return;
623 }
624 }
625 }
626 else
627 {
628 // Need to preserve the incorrect behavior until the fix amendment can be retired,
629 // because otherwise would risk an unplanned ledger fork.
630 ++mantissa;
631 // Ensure mantissa after incrementing fits within both the
632 // min/maxMantissa range and is a valid "rep".
634 {
635 // Don't use doDropDigit here
636 mantissa /= 10;
637 ++exponent;
638 }
639 }
640 }
641 else if (
644 {
645 // When rounding down a value in between kMaxRep, and kMaxRepUp, round to kMaxRep.
646 // Note that the decision for this rounding is dominated by the results of pushOverflow.
648 }
649 bringIntoRange(negative, mantissa, exponent);
652}
653
654template <UnsignedMantissa T>
655void
656Number::Guard::doRoundDown(bool& negative, T& mantissa, int& exponent) const
657{
658 // Do not pushOverflow here.
659
660 auto r = round();
662 {
663 // If there was any remainder, subtract 1 from the result. This is sufficient to get the
664 // best rounding.
665 XRPL_ASSERT(
667 "xrpl::Number::Guard::doRoundDown : mantissa is expected size");
668 if (r != Round::Exact)
669 {
670 --mantissa;
671 }
672 }
673 else
674 {
675 // Need to preserve the incorrect behavior until the fix amendment can be retired,
676 // because otherwise would risk an unplanned ledger fork.
677 if (r == Round::Up || (r == Round::Even && (mantissa & 1) == 1))
678 {
679 --mantissa;
680 if (mantissa < minMantissa)
681 {
682 mantissa *= 10;
683 --exponent;
684 }
685 }
686 }
687 bringIntoRange(negative, mantissa, exponent);
688}
689
690// Modify the result to the correctly rounded value
691void
693{
694 // Do not pushOverflow here.
695
696 auto r = round();
697 if (r == Round::Up || (r == Round::Even && (drops & 1) == 1))
698 {
699 if (drops >= kMaxRep)
700 {
701 static_assert(sizeof(InternalRep) == sizeof(rep));
702 // This should be impossible, because it's impossible to represent
703 // "kMaxRep + 0.6" in Number, regardless of the scale. There aren't
704 // enough digits available. You'd either get a mantissa of "kMaxRep"
705 // or "(kMaxRep + 1) / 10", neither of which will round up when
706 // converting to rep, though the latter might overflow _before_
707 // rounding.
708 Throw<std::overflow_error>(std::string(location)); // LCOV_EXCL_LINE
709 }
710 ++drops;
711 }
712 XRPL_ASSERT(drops >= 0, "xrpl::Number::Guard::doRound : positive magnitude");
713
714 if (isNegative())
715 drops = -drops;
716}
717
718// Number
719
720// Safely convert rep (int64) mantissa to internalrep (uint64). If the rep is
721// negative, returns the positive value. This takes a little extra work because
722// converting std::numeric_limits<std::int64_t>::min() flirts with UB, and can
723// vary across compilers.
726{
727 // If the mantissa is already positive, just return it
728 if (mantissa >= 0)
729 return mantissa;
730 // If the mantissa is negative, but fits within the positive range of rep,
731 // return it negated
733 return -mantissa;
734
735 // If the mantissa doesn't fit within the positive range, convert to
736 // int128_t, negate that, and cast it back down to the internalrep
737 // In practice, this is only going to cover the case of
738 // std::numeric_limits<rep>::min().
739 Int128T const temp = mantissa;
740 return static_cast<InternalRep>(-temp);
741}
742
743Number
745{
746 auto const& range = kRange.get();
747 return Number{false, range.min, -range.log, Number::Unchecked{}};
748}
749
750template <class T>
751void
753 bool& negative,
754 T& mantissa,
755 int& exponent,
758 MantissaRange::CuspRoundingFix cuspRoundingFix,
759 bool dropped)
760{
761 static constexpr auto kMinExponent = Number::kMinExponent;
762 static constexpr auto kMaxExponent = Number::kMaxExponent;
763 auto const repLimit = cuspRoundingFix >= MantissaRange::CuspRoundingFix::Enabled330
766
767 using Guard = Number::Guard;
768
769 static constexpr Number kZero = Number{};
770 if (mantissa == 0)
771 {
772 mantissa = kZero.mantissa_;
773 exponent = kZero.exponent_;
774 negative = kZero.negative_;
775 return;
776 }
777 auto m = mantissa;
778 while ((m < minMantissa) && (exponent > kMinExponent))
779 {
780 m *= 10;
781 --exponent;
782 }
783 Guard g(minMantissa, maxMantissa, cuspRoundingFix);
784 if (negative)
785 g.setNegative();
786 if (dropped)
787 g.setDropped();
788 while (m > maxMantissa)
789 {
790 if (exponent >= kMaxExponent)
791 throw std::overflow_error("Number::normalize 1");
792 g.doDropDigit(m, exponent);
793 }
794 if ((exponent < kMinExponent) || (m < minMantissa))
795 {
796 mantissa = kZero.mantissa_;
797 exponent = kZero.exponent_;
798 negative = kZero.negative_;
799 return;
800 }
801
802 // When using the largeRange, "m" needs fit within an int64, even if
803 // the final mantissa is going to end up larger to fit within the
804 // MantissaRange. Cut it down here so that the rounding will be done while
805 // it's smaller.
806 //
807 // Example: 9,900,000,000,000,123,456 > 9,223,372,036,854,775,807,
808 // so "m" will be modified to 990,000,000,000,012,345. Then that value
809 // will be rounded to 990,000,000,000,012,345 or
810 // 990,000,000,000,012,346, depending on the rounding mode. Finally,
811 // mantissa will be "m*10" so it fits within the range, and end up as
812 // 9,900,000,000,000,123,450 or 9,900,000,000,000,123,460.
813 // mantissa() will return mantissa / 10, and exponent() will return
814 // exponent + 1.
815 if (m > repLimit)
816 {
817 if (exponent >= kMaxExponent)
818 throw std::overflow_error("Number::normalize 1.5");
819 g.doDropDigit(m, exponent);
820 }
821 // Before modification, m should be within the min/max range. After
822 // modification, it must be less than repLimit. In other words, the original
823 // value should have been no more than repLimit * 10.
824 // (repLimit * 10 > maxMantissa)
825 XRPL_ASSERT_PARTS(m <= repLimit, "xrpl::doNormalize", "intermediate mantissa fits in limit");
826 mantissa = m;
827
828 g.doRoundUp(negative, mantissa, exponent, "Number::normalize 2");
829 XRPL_ASSERT_PARTS(
831 "xrpl::doNormalize",
832 "final mantissa fits in range");
833}
834
835template <>
836void
838 bool& negative,
839 UInt128T& mantissa,
840 int& exponent,
843 MantissaRange::CuspRoundingFix cuspRoundingFix)
844{
845 // Not used by every compiler version, and thus not necessarily
846 // counted by coverage build
847 // LCOV_EXCL_START
848 doNormalize(negative, mantissa, exponent, minMantissa, maxMantissa, cuspRoundingFix, false);
849 // LCOV_EXCL_STOP
850}
851
852template <>
853void
855 bool& negative,
856 unsigned long long& mantissa,
857 int& exponent,
860 MantissaRange::CuspRoundingFix cuspRoundingFix)
861{
862 // Not used by every compiler version, and thus not necessarily
863 // counted by coverage build
864 // LCOV_EXCL_START
865 doNormalize(negative, mantissa, exponent, minMantissa, maxMantissa, cuspRoundingFix, false);
866 // LCOV_EXCL_STOP
867}
868
869template <>
870void
872 bool& negative,
873 unsigned long& mantissa,
874 int& exponent,
877 MantissaRange::CuspRoundingFix cuspRoundingFix)
878{
879 doNormalize(negative, mantissa, exponent, minMantissa, maxMantissa, cuspRoundingFix, false);
880}
881
882void
884{
885 normalize(negative_, mantissa_, exponent_, range.min, range.max, range.cuspRoundingFix);
886}
887
888void
890{
891 normalize(
892 negative_,
893 mantissa_,
894 exponent_,
895 guard.minMantissa,
896 guard.maxMantissa,
897 guard.cuspRoundingFix);
898}
899
900// Copy the number, but set a new exponent. Because the mantissa doesn't change,
901// the result will be "mostly" normalized, but the exponent could go out of
902// range.
903Number
904Number::shiftExponent(int exponentDelta) const
905{
906 XRPL_ASSERT_PARTS(isnormal(), "xrpl::Number::shiftExponent", "normalized");
907 auto const newExponent = exponent_ + exponentDelta;
908 if (newExponent >= kMaxExponent)
909 throw std::overflow_error("Number::shiftExponent");
910 if (newExponent < kMinExponent)
911 {
912 return Number{};
913 }
914 Number const result{negative_, mantissa_, newExponent, Unchecked{}};
915 XRPL_ASSERT_PARTS(result.isnormal(), "xrpl::Number::shiftExponent", "result is normalized");
916 return result;
917}
918
919Number&
921{
922 static constexpr Number kZero = Number{};
923 if (y == kZero)
924 return *this;
925 if (*this == kZero)
926 {
927 *this = y;
928 return *this;
929 }
930 if (*this == -y)
931 {
932 *this = kZero;
933 return *this;
934 }
935
936 XRPL_ASSERT(isnormal() && y.isnormal(), "xrpl::Number::operator+=(Number) : is normal");
937 // *n = negative
938 // *s = sign
939 // *m = mantissa
940 // *e = exponent
941
942 // Need to use uint128_t, because large mantissas can overflow when added
943 // together.
944 bool xn = negative_;
945 UInt128T xm = mantissa_;
946 auto xe = exponent_;
947
948 bool const yn = y.negative_;
949 UInt128T ym = y.mantissa_;
950 auto ye = y.exponent_;
951 Guard g(kRange);
952
953 auto const& minMantissa = g.minMantissa;
954 auto const& maxMantissa = g.maxMantissa;
955 auto const cuspRoundingFix = g.cuspRoundingFix;
956
957 auto const repLimit =
959
960 // Bring the exponents of both values into agreement, so the mantissas are on the same scale
961 // and can be added directly together.
962
963 auto const upperLimit = static_cast<UInt128T>(g.minMantissa) * 1000;
964 // For the "adjust" lambda
965 // expandM / expandE: The values for which the mantissa will be expanded, and the exponent
966 // decreased to match. Mantissa won't be expanded beyond upperLimit.
967 // (37e8 == 37000e5 == 37000000e2)
968 // shrinkM / shrinkE: The values for which the mantissa will be shrunk, and exponent increased
969 // to match, if necessary.
970 auto const adjust = [&g, &upperLimit](
971 UInt128T& expandM, int& expandE, UInt128T& shrinkM, int& shrinkE) {
972 XRPL_ASSERT(shrinkE < expandE, "xrpl::Number::operator+= : exponents ordered correctly");
973 // Adjust up and down until the exponents match
975 {
976 // For Enabled330, there are three steps.
977 // 1. First, shrink the mantissa of shrinkM/shrinkE while shrinkM ends in 0.
978 while (shrinkE < expandE && shrinkM % 10 == 0)
979 {
980 // Don't use doDropDigitWithTarget here, because the loop will stop before the
981 // mantissa gets to 0.
982 g.doDropDigit(shrinkM, shrinkE);
983 }
984
985 // 2. Then expand the mantissa of expandM/expandE, with a limit for expandM a few orders
986 // of magnitude above the MantissaRange. This will leave a few extra digits for rounding
987 // later, but nothing excessive.
988 while (shrinkE < expandE && expandE > kMinExponent && expandM < upperLimit)
989 {
990 expandM *= 10;
991 --expandE;
992 }
993 }
994
995 // 3. Finally, shrink the mantissa of shrinkM/shrinkE until the exponents match. Any removed
996 // digits will be put into the Guard. This is the only step for non-Enabled330 modes.
997 if (shrinkE < expandE)
998 {
999 g.doDropDigitWithTarget(shrinkM, shrinkE, expandE);
1000 }
1001 XRPL_ASSERT(shrinkE == expandE, "xrpl::Number::operator+= : exponents are equal");
1002 };
1003
1004 // Shrink the mantissa and raise the exponent of the value with the lower exponent. Store any
1005 // dropped digits in the Guard.
1006 if (xe < ye)
1007 {
1008 if (xn)
1009 g.setNegative();
1010
1011 adjust(ym, ye, xm, xe);
1012 }
1013 else if (xe > ye)
1014 {
1015 if (yn)
1016 g.setNegative();
1017
1018 adjust(xm, xe, ym, ye);
1019 }
1021 {
1022 // Both values have the same exponent.
1023 // Set the sign of the Guard based on the sign of the Number with the smallest
1024 // unsigned _mantissa_
1025 if ((xm < ym && xn) || (ym < xm && yn))
1026 g.setNegative();
1027 }
1028
1029 if (xn == yn)
1030 {
1031 xm += ym;
1032
1034 {
1035 // Don't do any adjustments for Enabled330. Normalize will take care of it
1036 // Because of "adjust", the only way there can be data in the Guard is if we first grew
1037 // the mantissa past the maxMantissa. Since we added here, it can only get bigger.
1038 // If xm > maxMantissa, then doNormalize has all the data it needs from the last 3-4
1039 // digits, plus the "dropped" flag that will be passed in.
1040 // If not, then the mantissa will only need to be padded out with 0s and won't need to
1041 // round.
1042 XRPL_ASSERT(
1043 xm > maxMantissa || g.empty(),
1044 "xrpl::Number::operator+= : rounding state expected after add");
1045 }
1046 else
1047 {
1048 if (xm > maxMantissa || xm > repLimit)
1049 {
1050 g.doDropDigit(xm, xe);
1051 }
1052 g.doRoundUp(xn, xm, xe, "Number::addition overflow");
1053 }
1054 }
1055 else
1056 {
1057 if (xm > ym)
1058 {
1059 xm = xm - ym;
1060 }
1061 else
1062 {
1063 xm = ym - xm;
1064 xe = ye;
1065 xn = yn;
1066 }
1067 if (cuspRoundingFix >= MantissaRange::CuspRoundingFix::Enabled330)
1068 {
1069 // Because we subtracted, xm can have any number of digits from 1 up to
1070 // upperLimit * 10, and g can be in any state. (Note that xm can't be zero, because that
1071 // special case was tested earlier.)
1072
1073 // Grow xm/xe and pull digits out of the Guard until xm reaches upperLimit, but stop if
1074 // the Guard empties out, because no rounding will be necessary. This will ensure that
1075 // normalize will have enough information to make an accurate rounding decision.
1076 // (Normalize will pad a small mantissa back into range.) Note that if any digits were
1077 // lost (xbit_), the Guard will never be empty, so xm will grow larger than upperLimit.
1078 while (xm < upperLimit && !g.empty())
1079 {
1080 xm *= 10;
1081 xm -= g.pop();
1082 --xe;
1083 }
1084 XRPL_ASSERT(
1085 xm > maxMantissa || g.empty(),
1086 "xrpl::Number::operator+= : rounding state expected after subtract");
1087 }
1088 else
1089 {
1090 // Grow xm/xe and pull digits out of the Guard until it's back in the
1091 // minMantissa/maxMantissa range.
1092 while (xm < minMantissa && xm * 10 <= repLimit)
1093 {
1094 xm *= 10;
1095 xm -= g.pop();
1096 --xe;
1097 }
1098 }
1099 // Rounding down can result in decrementing xm, based on whether there is any data left in
1100 // the Guard (depending on cuspRoundingFix). Note that if that happens, then the Guard is
1101 // not empty. For Enabled330, that will also result in the "dropped" flag being passed to
1102 // doNormalize, which may result in the mantissa being incremented again. It doesn't matter
1103 // what the dropped digits are, only that they exist. This is because subtracting one
1104 // "overcorrects", so we know there are still trailing digits to be accounted for in the
1105 // rounding.
1106 //
1107 // This works because
1108 // 1. The rounding up will be done _after_ the mantissa is brought into range. It may not
1109 // be in range right now, and
1110 // 2. The "dropped" flag is only ever used as a tie-breaker, specifically when rounding
1111 // away from zero, and the dropped digits are 0, or when rounding to nearest, and
1112 // the dropped digits represent exactly 0.5.
1113 g.doRoundDown(xn, xm, xe);
1114 }
1115
1117 xn,
1118 xm,
1119 xe,
1122 cuspRoundingFix,
1123 cuspRoundingFix == MantissaRange::CuspRoundingFix::Enabled330 && !g.empty());
1124 negative_ = xn;
1125 mantissa_ = static_cast<InternalRep>(xm);
1126 exponent_ = xe;
1127 XRPL_ASSERT(isnormal(), "xrpl::Number::operator+= : result is normal");
1128 return *this;
1129}
1130
1131Number&
1133{
1134 static constexpr Number kZero = Number{};
1135 if (*this == kZero)
1136 return *this;
1137 if (y == kZero)
1138 {
1139 *this = y;
1140 return *this;
1141 }
1142 // *n = negative
1143 // *s = sign
1144 // *m = mantissa
1145 // *e = exponent
1146
1147 bool const xn = negative_;
1148 int const xs = xn ? -1 : 1;
1150 auto xe = exponent_;
1151
1152 bool const yn = y.negative_;
1153 int const ys = yn ? -1 : 1;
1154 InternalRep const ym = y.mantissa_;
1155 auto ye = y.exponent_;
1156
1157 auto zm = UInt128T(xm) * UInt128T(ym);
1158 auto ze = xe + ye;
1159 auto zs = xs * ys;
1160 bool zn = (zs == -1);
1161 Guard g(kRange);
1162 if (zn)
1163 g.setNegative();
1164
1165 auto const& maxMantissa = g.maxMantissa;
1166 auto const repLimit =
1168
1169 while (zm > maxMantissa || zm > repLimit)
1170 {
1171 g.doDropDigit(zm, ze);
1172 }
1173
1174 xm = static_cast<InternalRep>(zm);
1175 xe = ze;
1176 g.doRoundUp(zn, xm, xe, "Number::multiplication overflow : exponent is " + std::to_string(xe));
1177 negative_ = zn;
1178 mantissa_ = xm;
1179 exponent_ = xe;
1180
1181 normalize(g);
1182 return *this;
1183}
1184
1185Number&
1187{
1188 static constexpr Number kZero = Number{};
1189 if (y == kZero)
1190 throw std::overflow_error("Number: divide by 0");
1191 if (*this == kZero)
1192 return *this;
1193 // n* = numerator
1194 // d* = denominator
1195 // z* = result (quotient)
1196 // *p = negative (p for positive, even though the value means not
1197 // positive?)
1198 // *s = sign
1199 // *m = mantissa
1200 // *e = exponent
1201
1202 bool const np = negative_;
1203 int const ns = (np ? -1 : 1);
1204 auto nm = mantissa_;
1205 auto ne = exponent_;
1206
1207 bool const dp = y.negative_;
1208 int const ds = (dp ? -1 : 1);
1209 // Create the denominator as 128-bit unsigned, since that's what we
1210 // need to work with.
1211 auto const dm = static_cast<UInt128T>(y.mantissa_);
1212 auto const de = y.exponent_;
1213
1214 auto const& range = kRange.get();
1215 auto const& minMantissa = range.min;
1216 auto const& maxMantissa = range.max;
1217 auto const cuspRoundingFix = range.cuspRoundingFix;
1218
1219 // Division operates on two large integers (16-digit for small
1220 // mantissas, 19-digit for large) using integer math. If the values
1221 // were just divided directly, the result would be only ever be one
1222 // digit or zero - not very useful.
1223 // e.g. 9'876'543'210'987'654 / 1'234'567'890'123'456 = 8
1224 // 1'234'567'890'123'456 / 9'876'543'210'987'654 = 0
1225 // Introduce a power-of-ten multiplication factor for the numerator
1226 // which will ensure the result has a meaningful number of digits.
1227 //
1228 // Consider numbers with a 2-digit mantissa:
1229 // * Assume both numbers have an exponent of 0, using "ToNearest" rounding
1230 // * 23 / 67 = 0
1231 // * Use a factor of 10^4
1232 // * 230'000 / 67 = 3432 with an exponent of -4
1233 // * The normalized result will be 34, exponent -2, or 0.34
1234 //
1235 // The most extreme results are 10/99 and 99/10
1236 // * 100'000 / 99 = 1'010e-4 = 10e-2 or 0.10
1237 // * 990'000 / 10 = 99'000e-4 = 99e-1 or 9.9
1238 //
1239 // Note that the computations give 2 or 3 digits after the
1240 // decimal point to determine which way to round for most scenarios.
1241 //
1242 // For small mantissas (where the MantissaRange.log == 15), shifting by 10^17 gives sufficient
1243 // precision while not overflowing uint128_t or the cast back to int64_t. (This is legacy
1244 // behavior, which must not be changed.)
1245 //
1246 // For large mantissas (where the MantissaRange.log == 18), a shift by 10^20 would be optimal
1247 // for most scenarios. However, larger mantissa values would overflow 2^128.
1248 //
1249 // * log(2^128,10) ~ 38.5
1250 // * largeRange.log = 18, fits in 10^19
1251 // * The expanded numerator must fit in 10^38
1252 // * f not be more than 10^(38-19) = 10^19 safely
1253 //
1254 // So, we do the division into stages:
1255 //
1256 // Stage 1: Use the same factor of 10^17, for the initial division. This
1257 // will frequently not result in a whole number quotient.
1258 //
1259 // Stage 2: If there is a remainder from the first step, repeat the
1260 // process with a "correction" factor of 10^5. Shift the
1261 // result of Stage 1 over by 5 places, and add the second result to it.
1262 // This is equivalent to if we had used an initial factor of 10^22,
1263 // a couple digits more than we actually need.
1264 //
1265 // Stage 3: If there is still a remainder, and the cuspRoundingFix
1266 // is enabled, pass a flag indicating such to doNormalize. The Guard
1267 // in doNormalize will treat that flag as if non-zero digits had
1268 // been dropped from the mantissa when shrinking it into range.
1269 // This is only relevant when rounding away from zero (Upward for
1270 // positive numbers, Downward for negative), or if the "regular"
1271 // remainder is exactly 0.5 for "ToNearest". This will give the
1272 // rounding the most accurate result possible, as if infinite
1273 // precision was used in the initial calculation.
1274
1275 // Stage 1: Do the initial division with a factor of 10^17.
1276 auto constexpr factorExponent = 17;
1277
1278 UInt128T constexpr f = kPowerOfTen[factorExponent];
1279
1280 auto const numerator = UInt128T(nm) * f;
1281
1282 auto zm = numerator / dm;
1283 auto ze = ne - de - factorExponent;
1284 bool zp = (ns * ds) < 0;
1285 // dropped is used in the same way as Guard::xbit_. In the case of
1286 // division, it indicates if there's any remainder left over after
1287 // we have been as precise as reasonable. If there is, it would be as
1288 // if we were using infinite precision math, and a non-zero digit
1289 // had been shifted off the end of the result when normalizing.
1290 bool dropped = false;
1291
1293 {
1294 // Stage 2
1295 //
1296 // If there is a remainder, treat it as a secondary numerator.
1297 // Multiply by correctionFactor separately from stage 1.
1298 // The math for this would work for small mantissas, but we need to
1299 // preserve legacy behavior.
1300 //
1301 // Consider:
1302 // ((numerator * correctionFactor) / dm) / correctionFactor
1303 // = ((numerator / dm) * correctionFactor) / correctionFactor)
1304 //
1305 // But that assumes infinite precision. With integer math, this is
1306 // equivalent to
1307 //
1308 // = ((numerator / dm * correctionFactor)
1309 // + ((numerator % dm) * correctionFactor) / dm) / correctionFactor
1310 // = ((zm * correctionFactor)
1311 // + (remainder * correctionFactor) / dm) / correctionFactor
1312 //
1313 // The trick is that multiplication by correctionFactor is done on the mantissa, but
1314 // division by correctionFactor is done by modifying the exponent, so no precision is lost
1315 // until we normalize.
1316 //
1317 // If remainder is zero, we can skip this stage entirely because
1318 // the first stage gave an exact answer.
1319 auto constexpr correctionExponent = 5;
1320 UInt128T constexpr correctionFactor = kPowerOfTen[correctionExponent];
1321 static_assert(factorExponent + correctionExponent == 22);
1322
1323 auto const remainder = (numerator % dm);
1324 if (remainder != 0)
1325 {
1326 auto const partialNumerator = remainder * correctionFactor;
1327 auto const correction = partialNumerator / dm;
1328
1329 // If the correction is zero, we do not have to make any
1330 // modifications to z*, because it will not have any
1331 // effect on the final result. (We'd be adding a bunch of
1332 // zeros to the end of zm that would just be removed in
1333 // normalize.) However, if that is the case, then Stage 3 is
1334 // even more important for accuracy.
1335 if (correction != 0)
1336 {
1337 zm *= correctionFactor;
1338 // divide by the correctionFactor by moving the exponent, so we don't lose the
1339 // integer value we just computed
1340 ze -= correctionExponent;
1341
1342 zm += correction;
1343 }
1344
1345 // Stage 3: If there's still anything left, and the cusp
1346 // rounding fix is enabled, flag if there is still
1347 // a remainder from stage 2.
1348 bool const useTrailingRemainder =
1350 if (useTrailingRemainder)
1351 {
1352 dropped = partialNumerator % dm != 0;
1353 }
1354 }
1355 }
1356 doNormalize(zp, zm, ze, minMantissa, maxMantissa, cuspRoundingFix, dropped);
1357 negative_ = zp;
1358 mantissa_ = static_cast<InternalRep>(zm);
1359 exponent_ = ze;
1360 XRPL_ASSERT_PARTS(isnormal(), "xrpl::Number::operator/=", "result is normalized");
1361
1362 return *this;
1363}
1364
1365Number::
1366operator rep() const
1367{
1368 rep drops = mantissa();
1369 int offset = exponent();
1370 Guard g(kRange);
1371 if (drops != 0)
1372 {
1373 if (negative_)
1374 {
1375 g.setNegative();
1376 drops = -drops;
1377 }
1378 if (offset < 0)
1379 {
1380 g.doDropDigitWithTarget(drops, offset, 0);
1381 XRPL_ASSERT(offset == 0, "xrpl::Number::operator rep() : exponents are equal");
1382 }
1383 for (; offset > 0; --offset)
1384 {
1385 if (drops > kMaxRep / 10)
1386 throw std::overflow_error("Number::operator rep() overflow");
1387 drops *= 10;
1388 }
1389 g.doRound(drops, "Number::operator rep() rounding overflow");
1390 }
1391 return drops;
1392}
1393
1394Number
1395Number::truncate() const noexcept
1396{
1397 if (exponent_ >= 0 || mantissa_ == 0)
1398 return *this;
1399
1400 Number ret = *this;
1401 while (ret.exponent_ < 0 && ret.mantissa_ != 0)
1402 {
1403 ret.exponent_ += 1;
1404 ret.mantissa_ /= rep(10);
1405 }
1406 // We are guaranteed that normalize() will never throw an exception
1407 // because exponent is either negative or zero at this point.
1408 ret.normalize(kRange);
1409 return ret;
1410}
1411
1413to_string(Number const& amount)
1414{
1415 // keep full internal accuracy, but make more human friendly if possible
1416 static constexpr Number kZero = Number{};
1417 if (amount == kZero)
1418 return "0";
1419
1420 auto exponent = amount.exponent_;
1421 auto mantissa = amount.mantissa_;
1422 bool const negative = amount.negative_;
1423
1424 // Use scientific notation for exponents that are too small or too large
1425 auto const rangeLog = Number::mantissaLog();
1426 if (((exponent != 0) && ((exponent < -(rangeLog + 10)) || (exponent > -(rangeLog - 10)))))
1427 {
1428 while (mantissa != 0 && mantissa % 10 == 0 && exponent < Number::kMaxExponent)
1429 {
1430 mantissa /= 10;
1431 ++exponent;
1432 }
1433 std::string ret = negative ? "-" : "";
1435 if (exponent != 0)
1436 {
1437 ret.append(1, 'e');
1439 }
1440 return ret;
1441 }
1442
1443 XRPL_ASSERT(exponent + 43 > 0, "xrpl::to_string(Number) : minimum exponent");
1444
1445 ptrdiff_t const padPrefix = rangeLog + 12;
1446 ptrdiff_t const padSuffix = rangeLog + 8;
1447
1448 std::string const rawValue(std::to_string(mantissa));
1449 std::string val;
1450
1451 val.reserve(rawValue.length() + padPrefix + padSuffix);
1452 val.append(padPrefix, '0');
1453 val.append(rawValue);
1454 val.append(padSuffix, '0');
1455
1456 ptrdiff_t const offset(exponent + padPrefix + rangeLog + 1);
1457
1458 auto preFrom(val.begin());
1459 auto const preTo(val.begin() + offset);
1460
1461 auto const postFrom(val.begin() + offset);
1462 auto postTo(val.end());
1463
1464 // Crop leading zeroes. Take advantage of the fact that there's always a
1465 // fixed amount of leading zeroes and skip them.
1466 if (std::distance(preFrom, preTo) > padPrefix)
1467 preFrom += padPrefix;
1468
1469 XRPL_ASSERT(postTo >= postFrom, "xrpl::to_string(Number) : first distance check");
1470
1471 preFrom = std::find_if(preFrom, preTo, [](char c) { return c != '0'; });
1472
1473 // Crop trailing zeroes. Take advantage of the fact that there's always a
1474 // fixed amount of trailing zeroes and skip them.
1475 if (std::distance(postFrom, postTo) > padSuffix)
1476 postTo -= padSuffix;
1477
1478 XRPL_ASSERT(postTo >= postFrom, "xrpl::to_string(Number) : second distance check");
1479
1480 postTo = std::find_if(
1483 [](char c) { return c != '0'; })
1484 .base();
1485
1486 std::string ret;
1487
1488 if (negative)
1489 ret.append(1, '-');
1490
1491 // Assemble the output:
1492 if (preFrom == preTo)
1493 {
1494 ret.append(1, '0');
1495 }
1496 else
1497 {
1498 ret.append(preFrom, preTo);
1499 }
1500
1501 if (postTo != postFrom)
1502 {
1503 ret.append(1, '.');
1504 ret.append(postFrom, postTo);
1505 }
1506
1507 return ret;
1508}
1509
1510// Returns f^n
1511// Uses a log_2(n) number of multiplications
1512
1513Number
1514power(Number const& f, unsigned n)
1515{
1516 if (n == 0)
1517 return Number::one();
1518 if (n == 1)
1519 return f;
1520 auto r = power(f, n / 2);
1521 r *= r;
1522 if (n % 2 != 0)
1523 r *= f;
1524 return r;
1525}
1526
1527// Returns f^(1/d)
1528// Uses Newton–Raphson iterations until the result stops changing
1529// to find the non-negative root of the polynomial g(x) = x^d - f
1530
1531// This function, and power(Number f, unsigned n, unsigned d)
1532// treat corner cases such as 0 roots as advised by Annex F of
1533// the C standard, which itself is consistent with the IEEE
1534// floating point standards.
1535
1536Number
1537root(Number f, unsigned d)
1538{
1539 static constexpr Number kZero = Number{};
1540 auto const one = Number::one();
1541
1542 if (f == one || d == 1)
1543 return f;
1544 if (d == 0)
1545 {
1546 if (f == -one)
1547 return one;
1548 if (abs(f) < one)
1549 return kZero;
1550 throw std::overflow_error("Number::root infinity");
1551 }
1552 if (f < kZero && d % 2 == 0)
1553 throw std::overflow_error("Number::root nan");
1554 if (f == kZero)
1555 return f;
1556
1557 // Scale f into the range (0, 1) such that f's exponent is a multiple of d
1558 auto e = f.exponent_ + Number::mantissaLog() + 1;
1559 auto const di = static_cast<int>(d);
1560 auto ex = [e = e, di = di]() // Euclidean remainder of e/d
1561 {
1562 int const k = (e >= 0 ? e : e - (di - 1)) / di;
1563 int const k2 = e - (k * di);
1564 if (k2 == 0)
1565 return 0;
1566 return di - k2;
1567 }();
1568 e += ex;
1569 f = f.shiftExponent(-e); // f /= 10^e;
1570
1571 XRPL_ASSERT_PARTS(f.isnormal(), "xrpl::root(Number, unsigned)", "f is normalized");
1572 bool neg = false;
1573 if (f < kZero)
1574 {
1575 neg = true;
1576 f = -f;
1577 }
1578
1579 // Quadratic least squares curve fit of f^(1/d) in the range [0, 1]
1580
1581 // NOLINTNEXTLINE(readability-identifier-naming)
1582 auto const D = (((((6 * di) + 11) * di) + 6) * di) + 1;
1583 auto const a0 = 3 * di * ((((2 * di) - 3) * di) + 1);
1584 auto const a1 = 24 * di * ((2 * di) - 1);
1585 auto const a2 = -30 * (di - 1) * di;
1586 Number r = ((Number{a2} * f + Number{a1}) * f + Number{a0}) / Number{D};
1587 if (neg)
1588 {
1589 f = -f;
1590 r = -r;
1591 }
1592
1593 // Newton–Raphson iteration of f^(1/d) with initial guess r
1594 // halt when r stops changing, checking for bouncing on the last iteration
1595 Number rm1{};
1596 Number rm2{};
1597 do
1598 {
1599 rm2 = rm1;
1600 rm1 = r;
1601 r = (Number(d - 1) * r + f / power(r, d - 1)) / Number(d);
1602 } while (r != rm1 && r != rm2);
1603
1604 // return r * 10^(e/d) to reverse scaling
1605 auto const result = r.shiftExponent(e / di);
1606 XRPL_ASSERT_PARTS(result.isnormal(), "xrpl::root(Number, unsigned)", "result is normalized");
1607 return result;
1608}
1609
1610Number
1612{
1613 static constexpr Number kZero = Number{};
1614 auto const one = Number::one();
1615
1616 if (f == one)
1617 return f;
1618 if (f < kZero)
1619 throw std::overflow_error("Number::root nan");
1620 if (f == kZero)
1621 return f;
1622
1623 // Scale f into the range (0, 1) such that f's exponent is a multiple of d
1624 auto e = f.exponent_ + Number::mantissaLog() + 1;
1625 if (e % 2 != 0)
1626 ++e;
1627 f = f.shiftExponent(-e); // f /= 10^e;
1628 XRPL_ASSERT_PARTS(f.isnormal(), "xrpl::root2(Number)", "f is normalized");
1629
1630 // Quadratic least squares curve fit of f^(1/d) in the range [0, 1]
1631 auto const D = 105; // NOLINT(readability-identifier-naming)
1632 auto const a0 = 18;
1633 auto const a1 = 144;
1634 auto const a2 = -60;
1635 Number r = ((Number{a2} * f + Number{a1}) * f + Number{a0}) / Number{D};
1636
1637 // Newton–Raphson iteration of f^(1/2) with initial guess r
1638 // halt when r stops changing, checking for bouncing on the last iteration
1639 Number rm1{};
1640 Number rm2{};
1641 do
1642 {
1643 rm2 = rm1;
1644 rm1 = r;
1645 r = (r + f / r) / Number(2);
1646 } while (r != rm1 && r != rm2);
1647
1648 // return r * 10^(e/2) to reverse scaling
1649 auto const result = r.shiftExponent(e / 2);
1650 XRPL_ASSERT_PARTS(result.isnormal(), "xrpl::root2(Number)", "result is normalized");
1651
1652 return result;
1653}
1654
1655// Returns f^(n/d)
1656
1657Number
1658power(Number const& f, unsigned n, unsigned d)
1659{
1660 static constexpr Number kZero = Number{};
1661 auto const one = Number::one();
1662
1663 if (f == one)
1664 return f;
1665 auto g = std::gcd(n, d);
1666 if (g == 0)
1667 throw std::overflow_error("Number::power nan");
1668 if (d == 0)
1669 {
1670 if (f == -one)
1671 return one;
1672 if (abs(f) < one)
1673 return kZero;
1674 // abs(f) > one
1675 throw std::overflow_error("Number::power infinity");
1676 }
1677 if (n == 0)
1678 return one;
1679 n /= g;
1680 d /= g;
1681 if ((n % 2) == 1 && (d % 2) == 0 && f < kZero)
1682 throw std::overflow_error("Number::power nan");
1683 return root(power(f, n), d);
1684}
1685
1686} // namespace xrpl
T append(T... args)
T begin(T... args)
static constexpr MantissaRange const & mantissaRange(MantissaScale scale)
bool empty() const noexcept
bool isNegative() const noexcept
Guard(MantissaRange const &range)
void doDropDigit(T &mantissa, int &exponent) noexcept
Drop a digit from the mantissa, and increment the exponent, storing the dropped digit in this Guard.
bool unrecoverable() const noexcept
MantissaRange::CuspRoundingFix const cuspRoundingFix
void doRoundUp(bool &negative, T &mantissa, int &exponent, std::string location)
void doPush(unsigned d) noexcept
void doRoundDown(bool &negative, T &mantissa, int &exponent) const
Guard(InternalRep const &minMantissa, InternalRep const &maxMantissa, MantissaRange::CuspRoundingFix cuspRoundingFix)
void bringIntoRange(bool &negative, T &mantissa, int &exponent) const
void doDropDigitWithTarget(T &mantissa, int &exponent, int const targetExponent) noexcept
Drop a digit from the mantissa, and increment the exponent, storing the dropped digit in this Guard.
Round round() const noexcept
void doRound(rep &drops, std::string location) const
Number is a floating point type that can represent a wide range of values.
Definition Number.h:351
constexpr rep mantissa() const noexcept
Returns the mantissa of the external view of the Number.
Definition Number.h:692
Number & operator/=(Number const &x)
Number & operator+=(Number const &x)
static InternalRep maxMantissa()
Definition Number.h:568
MantissaRange::rep InternalRep
Definition Number.h:353
static constexpr InternalRep kMaxRepUp
Definition Number.h:367
Number truncate() const noexcept
std::int64_t rep
Definition Number.h:352
friend std::string to_string(Number const &amount)
static constexpr int kMinExponent
Definition Number.h:361
static RoundingMode setround(RoundingMode inMode)
static constexpr InternalRep kMaxRep
Definition Number.h:364
static RoundingMode mode
Definition Number.h:598
friend void doNormalize(bool &negative, T &mantissa, int &exponent, MantissaRange::rep const &minMantissa, MantissaRange::rep const &maxMantissa, MantissaRange::CuspRoundingFix cuspRoundingFix, bool dropped)
static Number max() noexcept
Definition Number.h:819
static RoundingMode getround()
static std::reference_wrapper< MantissaRange const > kRange
Definition Number.h:604
Number shiftExponent(int exponentDelta) const
static MantissaRange::MantissaScale getMantissaScale()
Returns which mantissa scale is currently in use for normalization.
static InternalRep minMantissa()
Definition Number.h:562
static constexpr int kMaxExponent
Definition Number.h:362
bool isnormal() const noexcept
Definition Number.h:831
constexpr int exponent() const noexcept
Returns the exponent of the external view of the Number.
Definition Number.h:714
friend Number root2(Number f)
static InternalRep externalToInternal(rep mantissa)
static Number min() noexcept
Definition Number.h:813
int exponent_
Definition Number.h:357
void normalize(MantissaRange const &range)
Number & operator*=(Number const &x)
constexpr Number()=default
static void setMantissaScale(MantissaRange::MantissaScale scale)
Changes which mantissa scale is used for normalization.
bool negative_
Definition Number.h:355
static int mantissaLog()
Definition Number.h:574
InternalRep mantissa_
Definition Number.h:356
friend Number root(Number f, unsigned d)
T distance(T... args)
T end(T... args)
T exchange(T... args)
T find_if(T... args)
T gcd(T... args)
T is_same_v
T is_unsigned_v
T make_reverse_iterator(T... args)
T max(T... args)
STL namespace.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
ClosedInterval< T > range(T low, T high)
Create a closed range interval.
Definition RangeSet.h:37
int scale(Number const &number, Asset const &asset)
Get the scale of a Number for a given asset.
Definition STAmount.h:794
Number root(Number f, unsigned d)
Number power(Number const &f, unsigned n)
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:657
void logicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
constexpr auto kPowerOfTen
Definition Number.h:88
static unsigned divu10(UInt128T &u)
constexpr bool isPowerOfTen(T value)
Definition Number.h:43
constexpr Number abs(Number x) noexcept
Definition Number.h:876
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:52
T reserve(T... args)
T length(T... args)
MantissaRange defines a range for the mantissa of a normalized Number.
Definition Number.h:131
rep const min
Definition Number.h:173
MantissaScale const scale
Definition Number.h:171
std::uint64_t rep
Definition Number.h:132
int const log
Definition Number.h:172
CuspRoundingFix const cuspRoundingFix
Definition Number.h:175
constexpr MantissaRange(MantissaScale sc)
Definition Number.h:167
static std::set< MantissaScale > const & getAllScales()
Definition Number.h:178
rep const max
Definition Number.h:174
T to_string(T... args)