xrpld
Loading...
Searching...
No Matches
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 <unordered_map>
18#include <utility>
19
20#ifdef _MSC_VER
21#pragma message("Using boost::multiprecision::uint128_t and int128_t")
22#include <boost/multiprecision/cpp_int.hpp>
23using uint128_t = boost::multiprecision::uint128_t;
24using int128_t = boost::multiprecision::int128_t;
25#else // !defined(_MSC_VER)
26using uint128_t = __uint128_t;
27using int128_t = __int128_t;
28#endif // !defined(_MSC_VER)
29
30namespace xrpl {
31
33thread_local std::reference_wrapper<MantissaRange const> Number::kRange =
35
36std::set<MantissaRange::MantissaScale> const&
46
49{
50 static auto const kMap = []() {
52 for (auto const scale : getAllScales())
53 {
54 map.emplace(scale, scale);
55 }
56
57 // Use these constexpr declarations to do static_asserts to verify the MantissaRanges are
58 // created correctly, but nothing else.
59 {
60 [[maybe_unused]]
62 static_assert(isPowerOfTen(kRange.min));
63 static_assert(kRange.min == 1'000'000'000'000'000LL);
64 static_assert(kRange.max == 9'999'999'999'999'999LL);
65 static_assert(kRange.log == 15);
66 static_assert(kRange.min < Number::kMaxRep);
67 static_assert(kRange.max < Number::kMaxRep);
69 }
70 {
71 [[maybe_unused]]
73 static_assert(isPowerOfTen(kRange.min));
74 static_assert(kRange.min == 1'000'000'000'000'000'000ULL);
75 static_assert(kRange.max == rep(9'999'999'999'999'999'999ULL));
76 static_assert(kRange.log == 18);
77 static_assert(kRange.min < Number::kMaxRep);
78 static_assert(kRange.max > Number::kMaxRep);
80 }
81 {
82 [[maybe_unused]]
84 static_assert(isPowerOfTen(kRange.min));
85 static_assert(kRange.min == 1'000'000'000'000'000'000ULL);
86 static_assert(kRange.max == rep(9'999'999'999'999'999'999ULL));
87 static_assert(kRange.log == 18);
88 static_assert(kRange.min < Number::kMaxRep);
89 static_assert(kRange.max > Number::kMaxRep);
90 static_assert(kRange.cuspRoundingFixEnabled == CuspRoundingFix::Enabled);
91 }
92 return map;
93 }();
94
95 return kMap;
96}
97
98MantissaRange const&
103
106{
107 return mode;
108}
109
112{
113 return std::exchange(Number::mode, inMode);
114}
115
118{
119 return kRange.get().scale;
120}
121
122void
129
130// Optimization equivalent to:
131// auto r = static_cast<unsigned>(u % 10);
132// u /= 10;
133// return r;
134// Derived from Hacker's Delight Second Edition Chapter 10
135// by Henry S. Warren, Jr.
136static inline unsigned
137divu10(uint128_t& u)
138{
139 // q = u * 0.75
140 auto q = (u >> 1) + (u >> 2);
141 // iterate towards q = u * 0.8
142 q += q >> 4;
143 q += q >> 8;
144 q += q >> 16;
145 q += q >> 32;
146 q += q >> 64;
147 // q /= 8 approximately == u / 10
148 q >>= 3;
149 // r = u - q * 10 approximately == u % 10
150 auto r = static_cast<unsigned>(u - ((q << 3) + (q << 1)));
151 // correction c is 1 if r >= 10 else 0
152 auto c = (r + 6) >> 4;
153 u = q + c;
154 r -= c * 10;
155 return r;
156}
157
158// Guard
159
160// The Guard class is used to temporarily add extra digits of
161// precision to an operation. This enables the final result
162// to be correctly rounded to the internal precision of Number.
163
164template <class T>
166
168{
169 std::uint64_t digits_{0}; // 16 decimal guard digits
170 std::uint8_t xbit_ : 1 {0}; // has a non-zero digit been shifted off the end
171 std::uint8_t sbit_ : 1 {0}; // the sign of the guard digits
172
173public:
174 explicit Guard() = default;
175
176 // set & test the sign bit
177 void
178 setPositive() noexcept;
179 void
180 setNegative() noexcept;
181 // Should only be called by doNormalize, and then only for division
182 // operations with remainders.
183 void
184 setDropped() noexcept;
185 [[nodiscard]] bool
186 isNegative() const noexcept;
187
188 // add a digit
189 template <class T>
190 void
191 push(T d) noexcept;
192
193 // recover a digit
194 unsigned
195 pop() noexcept;
196
205 template <class T>
206 void
207 doDropDigit(T& mantissa, int& exponent) noexcept;
208
209 // Indicate round direction: 1 is up, -1 is down, 0 is even
210 // This enables the client to round towards nearest, and on
211 // tie, round towards even.
212 [[nodiscard]] int
213 round() const noexcept;
214
215 // Modify the result to the correctly rounded value
216 template <UnsignedMantissa T>
217 void
218 doRoundUp(
219 bool& negative,
220 T& mantissa,
221 int& exponent,
224 MantissaRange::CuspRoundingFix cuspRoundingFixEnabled,
225 std::string location);
226
227 // Modify the result to the correctly rounded value
228 template <UnsignedMantissa T>
229 void
230 doRoundDown(bool& negative, T& mantissa, int& exponent, internalrep const& minMantissa);
231
232 // Modify the result to the correctly rounded value
233 void
234 doRound(rep& drops, std::string location) const;
235
236private:
237 void
238 doPush(unsigned d) noexcept;
239
240 template <UnsignedMantissa T>
241 void
242 bringIntoRange(bool& negative, T& mantissa, int& exponent, internalrep const& minMantissa);
243};
244
245inline void
247{
248 sbit_ = 0;
249}
250
251inline void
253{
254 sbit_ = 1;
255}
256
257inline void
259{
260 xbit_ = 1;
261}
262
263inline bool
265{
266 return sbit_ == 1;
267}
268
269inline void
270Number::Guard::doPush(unsigned d) noexcept
271{
272 xbit_ = xbit_ || ((digits_ & 0x0000'0000'0000'000F) != 0);
273 digits_ >>= 4;
274 digits_ |= (d & 0x0000'0000'0000'000FULL) << 60;
275}
276
277template <class T>
278inline void
280{
281 doPush(static_cast<unsigned>(d));
282}
283
284inline unsigned
286{
287 unsigned const d = (digits_ & 0xF000'0000'0000'0000) >> 60;
288 digits_ <<= 4;
289 return d;
290}
291
292template <class T>
293void
295{
296 push(mantissa % 10);
297 mantissa /= 10;
298 ++exponent;
299}
300
301// Use the divu10 optimization for uint128s
302template <>
303void
305{
306 // The following is optimization for:
307 // push(static_cast<unsigned>(mantissa % 10));
308 // mantissa /= 10;
310 ++exponent;
311}
312
313// Returns:
314// -1 if Guard is less than half
315// 0 if Guard is exactly half
316// 1 if Guard is greater than half
317int
318Number::Guard::round() const noexcept
319{
320 auto mode = Number::getround();
321
323 return -1;
324
326 {
327 if (sbit_)
328 {
329 if (digits_ > 0 || xbit_)
330 return 1;
331 }
332 return -1;
333 }
334
336 {
337 if (sbit_)
338 return -1;
339 if (digits_ > 0 || xbit_)
340 return 1;
341 return -1;
342 }
343
344 // assume round to nearest if mode is not one of the predefined values
345 if (digits_ > 0x5000'0000'0000'0000)
346 return 1;
347 if (digits_ < 0x5000'0000'0000'0000)
348 return -1;
349 if (xbit_)
350 return 1;
351 return 0;
352}
353
354template <UnsignedMantissa T>
355void
357 bool& negative,
358 T& mantissa,
359 int& exponent,
361{
362 // Bring mantissa back into the minMantissa / maxMantissa range AFTER
363 // rounding
364 if (mantissa < minMantissa)
365 {
366 mantissa *= 10;
367 --exponent;
368 }
370 {
371 static constexpr Number kZero = Number{};
372
373 negative = kZero.negative_;
374 mantissa = kZero.mantissa_;
375 exponent = kZero.exponent_;
376 }
377}
378
379template <UnsignedMantissa T>
380void
382 bool& negative,
383 T& mantissa,
384 int& exponent,
387 MantissaRange::CuspRoundingFix cuspRoundingFixEnabled,
388 std::string location)
389{
390 auto r = round();
391 if (r == 1 || (r == 0 && (mantissa & 1) == 1))
392 {
393 auto const safeToIncrement = [&maxMantissa](auto const& mantissa) {
394 return mantissa < maxMantissa && mantissa < kMaxRep;
395 };
396 if (cuspRoundingFixEnabled == MantissaRange::CuspRoundingFix::Enabled)
397 {
398 // Ensure mantissa after incrementing fits within both the
399 // min/maxMantissa range and is a valid "rep".
400 if (safeToIncrement(mantissa))
401 {
402 // Nothing unusual here, just increment the mantissa
403 ++mantissa;
404 }
405 else
406 {
407 // Incrementing the mantissa will require dividing, which will require rounding. So
408 // _don't_ increment the mantissa. Instead, divide and round recursively. It should
409 // be impossible to recurse more than once, because once the mantissa is divided by
410 // 10, it will be _well_ under maxMantissa and kMaxRep, so adding 1 will have no
411 // chance of bringing it back over.
413 XRPL_ASSERT_PARTS(
414 safeToIncrement(mantissa),
415 "xrpl::Number::Guard::doRoundUp",
416 "can't recurse more than once");
417 doRoundUp(
418 negative,
419 mantissa,
420 exponent,
423 cuspRoundingFixEnabled,
424 location);
425 return;
426 }
427 }
428 else
429 {
430 // Need to preserve the incorrect behavior until the fix amendment can be retired,
431 // because otherwise would risk an unplanned ledger fork.
432 ++mantissa;
433 // Ensure mantissa after incrementing fits within both the
434 // min/maxMantissa range and is a valid "rep".
436 {
437 // Don't use doDropDigit here
438 mantissa /= 10;
439 ++exponent;
440 }
441 }
442 }
446}
447
448template <UnsignedMantissa T>
449void
451 bool& negative,
452 T& mantissa,
453 int& exponent,
455{
456 auto r = round();
457 if (r == 1 || (r == 0 && (mantissa & 1) == 1))
458 {
459 --mantissa;
460 if (mantissa < minMantissa)
461 {
462 mantissa *= 10;
463 --exponent;
464 }
465 }
467}
468
469// Modify the result to the correctly rounded value
470void
472{
473 auto r = round();
474 if (r == 1 || (r == 0 && (drops & 1) == 1))
475 {
476 if (drops >= kMaxRep)
477 {
478 static_assert(sizeof(internalrep) == sizeof(rep));
479 // This should be impossible, because it's impossible to represent
480 // "kMaxRep + 0.6" in Number, regardless of the scale. There aren't
481 // enough digits available. You'd either get a mantissa of "kMaxRep"
482 // or "(kMaxRep + 1) / 10", neither of which will round up when
483 // converting to rep, though the latter might overflow _before_
484 // rounding.
485 Throw<std::overflow_error>(std::string(location)); // LCOV_EXCL_LINE
486 }
487 ++drops;
488 }
489 if (isNegative())
490 drops = -drops;
491}
492
493// Number
494
495// Safely convert rep (int64) mantissa to internalrep (uint64). If the rep is
496// negative, returns the positive value. This takes a little extra work because
497// converting std::numeric_limits<std::int64_t>::min() flirts with UB, and can
498// vary across compilers.
501{
502 // If the mantissa is already positive, just return it
503 if (mantissa >= 0)
504 return mantissa;
505 // If the mantissa is negative, but fits within the positive range of rep,
506 // return it negated
508 return -mantissa;
509
510 // If the mantissa doesn't fit within the positive range, convert to
511 // int128_t, negate that, and cast it back down to the internalrep
512 // In practice, this is only going to cover the case of
513 // std::numeric_limits<rep>::min().
514 int128_t const temp = mantissa;
515 return static_cast<internalrep>(-temp);
516}
517
518Number
520{
521 auto const& range = kRange.get();
522 return Number{false, range.min, -range.log, Number::Unchecked{}};
523}
524
525template <class T>
526void
528 bool& negative,
529 T& mantissa,
530 int& exponent,
533 MantissaRange::CuspRoundingFix cuspRoundingFixEnabled,
534 bool dropped)
535{
536 static constexpr auto kMinExponent = Number::kMinExponent;
537 static constexpr auto kMaxExponent = Number::kMaxExponent;
538 static constexpr auto kMaxRep = Number::kMaxRep;
539
540 using Guard = Number::Guard;
541
542 static constexpr Number kZero = Number{};
543 if (mantissa == 0)
544 {
545 mantissa = kZero.mantissa_;
546 exponent = kZero.exponent_;
547 negative = kZero.negative_;
548 return;
549 }
550 auto m = mantissa;
551 while ((m < minMantissa) && (exponent > kMinExponent))
552 {
553 m *= 10;
554 --exponent;
555 }
556 Guard g;
557 if (negative)
558 g.setNegative();
559 if (dropped)
560 g.setDropped();
561 while (m > maxMantissa)
562 {
563 if (exponent >= kMaxExponent)
564 throw std::overflow_error("Number::normalize 1");
565 g.doDropDigit(m, exponent);
566 }
567 if ((exponent < kMinExponent) || (m < minMantissa))
568 {
569 mantissa = kZero.mantissa_;
570 exponent = kZero.exponent_;
571 negative = kZero.negative_;
572 return;
573 }
574
575 // When using the largeRange, "m" needs fit within an int64, even if
576 // the final mantissa is going to end up larger to fit within the
577 // MantissaRange. Cut it down here so that the rounding will be done while
578 // it's smaller.
579 //
580 // Example: 9,900,000,000,000,123,456 > 9,223,372,036,854,775,807,
581 // so "m" will be modified to 990,000,000,000,012,345. Then that value
582 // will be rounded to 990,000,000,000,012,345 or
583 // 990,000,000,000,012,346, depending on the rounding mode. Finally,
584 // mantissa will be "m*10" so it fits within the range, and end up as
585 // 9,900,000,000,000,123,450 or 9,900,000,000,000,123,460.
586 // mantissa() will return mantissa / 10, and exponent() will return
587 // exponent + 1.
588 if (m > kMaxRep)
589 {
590 if (exponent >= kMaxExponent)
591 throw std::overflow_error("Number::normalize 1.5");
592 g.doDropDigit(m, exponent);
593 }
594 // Before modification, m should be within the min/max range. After
595 // modification, it must be less than kMaxRep. In other words, the original
596 // value should have been no more than kMaxRep * 10.
597 // (kMaxRep * 10 > maxMantissa)
598 XRPL_ASSERT_PARTS(m <= kMaxRep, "xrpl::doNormalize", "intermediate mantissa fits in int64");
599 mantissa = m;
600
601 g.doRoundUp(
602 negative,
603 mantissa,
604 exponent,
607 cuspRoundingFixEnabled,
608 "Number::normalize 2");
609 XRPL_ASSERT_PARTS(
611 "xrpl::doNormalize",
612 "final mantissa fits in range");
613}
614
615template <>
616void
618 bool& negative,
619 uint128_t& mantissa,
620 int& exponent,
623 MantissaRange::CuspRoundingFix cuspRoundingFixEnabled)
624{
625 // Not used by every compiler version, and thus not necessarily
626 // counted by coverage build
627 // LCOV_EXCL_START
629 negative, mantissa, exponent, minMantissa, maxMantissa, cuspRoundingFixEnabled, false);
630 // LCOV_EXCL_STOP
631}
632
633template <>
634void
636 bool& negative,
637 unsigned long long& mantissa,
638 int& exponent,
641 MantissaRange::CuspRoundingFix cuspRoundingFixEnabled)
642{
643 // Not used by every compiler version, and thus not necessarily
644 // counted by coverage build
645 // LCOV_EXCL_START
647 negative, mantissa, exponent, minMantissa, maxMantissa, cuspRoundingFixEnabled, false);
648 // LCOV_EXCL_STOP
649}
650
651template <>
652void
654 bool& negative,
655 unsigned long& mantissa,
656 int& exponent,
659 MantissaRange::CuspRoundingFix cuspRoundingFixEnabled)
660{
662 negative, mantissa, exponent, minMantissa, maxMantissa, cuspRoundingFixEnabled, false);
663}
664
665void
667{
668 normalize(negative_, mantissa_, exponent_, range.min, range.max, range.cuspRoundingFixEnabled);
669}
670
671// Copy the number, but set a new exponent. Because the mantissa doesn't change,
672// the result will be "mostly" normalized, but the exponent could go out of
673// range.
674Number
675Number::shiftExponent(int exponentDelta) const
676{
677 XRPL_ASSERT_PARTS(isnormal(), "xrpl::Number::shiftExponent", "normalized");
678 auto const newExponent = exponent_ + exponentDelta;
679 if (newExponent >= kMaxExponent)
680 throw std::overflow_error("Number::shiftExponent");
681 if (newExponent < kMinExponent)
682 {
683 return Number{};
684 }
685 Number const result{negative_, mantissa_, newExponent, Unchecked{}};
686 XRPL_ASSERT_PARTS(result.isnormal(), "xrpl::Number::shiftExponent", "result is normalized");
687 return result;
688}
689
690Number&
692{
693 static constexpr Number kZero = Number{};
694 if (y == kZero)
695 return *this;
696 if (*this == kZero)
697 {
698 *this = y;
699 return *this;
700 }
701 if (*this == -y)
702 {
703 *this = kZero;
704 return *this;
705 }
706
707 XRPL_ASSERT(isnormal() && y.isnormal(), "xrpl::Number::operator+=(Number) : is normal");
708 // *n = negative
709 // *s = sign
710 // *m = mantissa
711 // *e = exponent
712
713 // Need to use uint128_t, because large mantissas can overflow when added
714 // together.
715 bool xn = negative_;
716 uint128_t xm = mantissa_;
717 auto xe = exponent_;
718
719 bool const yn = y.negative_;
720 uint128_t ym = y.mantissa_;
721 auto ye = y.exponent_;
722 Guard g;
723 if (xe < ye)
724 {
725 if (xn)
726 g.setNegative();
727 do
728 {
729 g.doDropDigit(xm, xe);
730 } while (xe < ye);
731 }
732 else if (xe > ye)
733 {
734 if (yn)
735 g.setNegative();
736 do
737 {
738 g.doDropDigit(ym, ye);
739 } while (xe > ye);
740 }
741
742 auto const& range = kRange.get();
743 auto const& minMantissa = range.min;
744 auto const& maxMantissa = range.max;
745 auto const cuspRoundingFixEnabled = range.cuspRoundingFixEnabled;
746
747 if (xn == yn)
748 {
749 xm += ym;
750 if (xm > maxMantissa || xm > kMaxRep)
751 {
752 g.doDropDigit(xm, xe);
753 }
754 g.doRoundUp(
755 xn,
756 xm,
757 xe,
760 cuspRoundingFixEnabled,
761 "Number::addition overflow");
762 }
763 else
764 {
765 if (xm > ym)
766 {
767 xm = xm - ym;
768 }
769 else
770 {
771 xm = ym - xm;
772 xe = ye;
773 xn = yn;
774 }
775 while (xm < minMantissa && xm * 10 <= kMaxRep)
776 {
777 xm *= 10;
778 xm -= g.pop();
779 --xe;
780 }
781 g.doRoundDown(xn, xm, xe, minMantissa);
782 }
783
784 negative_ = xn;
785 mantissa_ = static_cast<internalrep>(xm);
786 exponent_ = xe;
788 return *this;
789}
790
791Number&
793{
794 static constexpr Number kZero = Number{};
795 if (*this == kZero)
796 return *this;
797 if (y == kZero)
798 {
799 *this = y;
800 return *this;
801 }
802 // *n = negative
803 // *s = sign
804 // *m = mantissa
805 // *e = exponent
806
807 bool const xn = negative_;
808 int const xs = xn ? -1 : 1;
810 auto xe = exponent_;
811
812 bool const yn = y.negative_;
813 int const ys = yn ? -1 : 1;
814 internalrep const ym = y.mantissa_;
815 auto ye = y.exponent_;
816
817 auto zm = uint128_t(xm) * uint128_t(ym);
818 auto ze = xe + ye;
819 auto zs = xs * ys;
820 bool zn = (zs == -1);
821 Guard g;
822 if (zn)
823 g.setNegative();
824
825 auto const& range = kRange.get();
826 auto const& minMantissa = range.min;
827 auto const& maxMantissa = range.max;
828 auto const cuspRoundingFixEnabled = range.cuspRoundingFixEnabled;
829
830 while (zm > maxMantissa || zm > kMaxRep)
831 {
832 g.doDropDigit(zm, ze);
833 }
834
835 xm = static_cast<internalrep>(zm);
836 xe = ze;
837 g.doRoundUp(
838 zn,
839 xm,
840 xe,
843 cuspRoundingFixEnabled,
844 "Number::multiplication overflow : exponent is " + std::to_string(xe));
845 negative_ = zn;
846 mantissa_ = xm;
847 exponent_ = xe;
848
850 return *this;
851}
852
853Number&
855{
856 static constexpr Number kZero = Number{};
857 if (y == kZero)
858 throw std::overflow_error("Number: divide by 0");
859 if (*this == kZero)
860 return *this;
861 // n* = numerator
862 // d* = denominator
863 // z* = result (quotient)
864 // *p = negative (p for positive, even though the value means not
865 // positive?)
866 // *s = sign
867 // *m = mantissa
868 // *e = exponent
869
870 bool const np = negative_;
871 int const ns = (np ? -1 : 1);
872 auto nm = mantissa_;
873 auto ne = exponent_;
874
875 bool const dp = y.negative_;
876 int const ds = (dp ? -1 : 1);
877 // Create the denominator as 128-bit unsigned, since that's what we
878 // need to work with.
879 uint128_t const dm = static_cast<uint128_t>(y.mantissa_);
880 auto const de = y.exponent_;
881
882 auto const& range = kRange.get();
883 auto const& minMantissa = range.min;
884 auto const& maxMantissa = range.max;
885 auto const cuspRoundingFixEnabled = range.cuspRoundingFixEnabled;
886
887 // Division operates on two large integers (16-digit for small
888 // mantissas, 19-digit for large) using integer math. If the values
889 // were just divided directly, the result would be only ever be one
890 // digit or zero - not very useful.
891 // e.g. 9'876'543'210'987'654 / 1'234'567'890'123'456 = 8
892 // 1'234'567'890'123'456 / 9'876'543'210'987'654 = 0
893 // Introduce a power-of-ten multiplication factor for the numerator
894 // which will ensure the result has a meaningful number of digits.
895 //
896 // Consider numbers with a 2-digit mantissa:
897 // * Assume both numbers have an exponent of 0, using "ToNearest" rounding
898 // * 23 / 67 = 0
899 // * Use a factor of 10^4
900 // * 230'000 / 67 = 3432 with an exponent of -4
901 // * The normalized result will be 34, exponent -2, or 0.34
902 //
903 // The most extreme results are 10/99 and 99/10
904 // * 100'000 / 99 = 1'010e-4 = 10e-2 or 0.10
905 // * 990'000 / 10 = 99'000e-4 = 99e-1 or 9.9
906 //
907 // Note that the computations give 2 or 3 digits after the
908 // decimal point to determine which way to round for most scenarios.
909 //
910 // For small mantissas (where the MantissaRange.log == 15), shifting by 10^17 gives sufficient
911 // precision while not overflowing uint128_t or the cast back to int64_t. (This is legacy
912 // behavior, which must not be changed.)
913 //
914 // For large mantissas (where the MantissaRange.log == 18), a shift by 10^20 would be optimal
915 // for most scenarios. However, larger mantissa values would overflow 2^128.
916 //
917 // * log(2^128,10) ~ 38.5
918 // * largeRange.log = 18, fits in 10^19
919 // * The expanded numerator must fit in 10^38
920 // * f not be more than 10^(38-19) = 10^19 safely
921 //
922 // So, we do the division into stages:
923 //
924 // Stage 1: Use the same factor of 10^17, for the initial division. This
925 // will frequently not result in a whole number quotient.
926 //
927 // Stage 2: If there is a remainder from the first step, repeat the
928 // process with a "correction" factor of 10^5. Shift the
929 // result of Stage 1 over by 5 places, and add the second result to it.
930 // This is equivalent to if we had used an initial factor of 10^22,
931 // a couple digits more than we actually need.
932 //
933 // Stage 3: If there is still a remainder, and the CuspRoundingFix
934 // is enabled, pass a flag indicating such to doNormalize. The Guard
935 // in doNormalize will treat that flag as if non-zero digits had
936 // been dropped from the mantissa when shrinking it into range.
937 // This is only relevant when rounding away from zero (Upward for
938 // positive numbers, Downward for negative), or if the "regular"
939 // remainder is exactly 0.5 for "ToNearest". This will give the
940 // rounding the most accurate result possible, as if infinite
941 // precision was used in the initial calculation.
942
943 // Stage 1: Do the initial division with a factor of 10^17.
944 auto constexpr factorExponent = 17;
945
946 uint128_t constexpr f = kPowerOfTen[factorExponent];
947
948 auto const numerator = uint128_t(nm) * f;
949
950 auto zm = numerator / dm;
951 auto ze = ne - de - factorExponent;
952 bool zp = (ns * ds) < 0;
953 // dropped is used in the same way as Guard::xbit_. In the case of
954 // division, it indicates if there's any remainder left over after
955 // we have been as precise as reasonable. If there is, it would be as
956 // if we were using infinite precision math, and a non-zero digit
957 // had been shifted off the end of the result when normalizing.
958 bool dropped = false;
959
961 {
962 // Stage 2
963 //
964 // If there is a remainder, treat it as a secondary numerator.
965 // Multiply by correctionFactor separately from stage 1.
966 // The math for this would work for small mantissas, but we need to
967 // preserve legacy behavior.
968 //
969 // Consider:
970 // ((numerator * correctionFactor) / dm) / correctionFactor
971 // = ((numerator / dm) * correctionFactor) / correctionFactor)
972 //
973 // But that assumes infinite precision. With integer math, this is
974 // equivalent to
975 //
976 // = ((numerator / dm * correctionFactor)
977 // + ((numerator % dm) * correctionFactor) / dm) / correctionFactor
978 // = ((zm * correctionFactor)
979 // + (remainder * correctionFactor) / dm) / correctionFactor
980 //
981 // The trick is that multiplication by correctionFactor is done on the mantissa, but
982 // division by correctionFactor is done by modifying the exponent, so no precision is lost
983 // until we normalize.
984 //
985 // If remainder is zero, we can skip this stage entirely because
986 // the first stage gave an exact answer.
987 auto constexpr correctionExponent = 5;
988 uint128_t constexpr correctionFactor = kPowerOfTen[correctionExponent];
989 static_assert(factorExponent + correctionExponent == 22);
990
991 auto const remainder = (numerator % dm);
992 if (remainder != 0)
993 {
994 auto const partialNumerator = remainder * correctionFactor;
995 auto const correction = partialNumerator / dm;
996
997 // If the correction is zero, we do not have to make any
998 // modifications to z*, because it will not have any
999 // effect on the final result. (We'd be adding a bunch of
1000 // zeros to the end of zm that would just be removed in
1001 // normalize.) However, if that is the case, then Stage 3 is
1002 // even more important for accuracy.
1003 if (correction != 0)
1004 {
1005 zm *= correctionFactor;
1006 // divide by the correctionFactor by moving the exponent, so we don't lose the
1007 // integer value we just computed
1008 ze -= correctionExponent;
1009
1010 zm += correction;
1011 }
1012
1013 // Stage 3: If there's still anything left, and the cusp
1014 // rounding fix is enabled, flag if there is still
1015 // a remainder from stage 2.
1016 bool const useTrailingRemainder =
1017 cuspRoundingFixEnabled == MantissaRange::CuspRoundingFix::Enabled;
1018 if (useTrailingRemainder)
1019 {
1020 dropped = partialNumerator % dm != 0;
1021 }
1022 }
1023 }
1024 doNormalize(zp, zm, ze, minMantissa, maxMantissa, cuspRoundingFixEnabled, dropped);
1025 negative_ = zp;
1026 mantissa_ = static_cast<internalrep>(zm);
1027 exponent_ = ze;
1028 XRPL_ASSERT_PARTS(isnormal(), "xrpl::Number::operator/=", "result is normalized");
1029
1030 return *this;
1031}
1032
1033Number::
1034operator rep() const
1035{
1036 rep drops = mantissa();
1037 int offset = exponent();
1038 Guard g;
1039 if (drops != 0)
1040 {
1041 if (negative_)
1042 {
1043 g.setNegative();
1044 drops = -drops;
1045 }
1046 while (offset < 0)
1047 {
1048 g.doDropDigit(drops, offset);
1049 }
1050 for (; offset > 0; --offset)
1051 {
1052 if (drops > kMaxRep / 10)
1053 throw std::overflow_error("Number::operator rep() overflow");
1054 drops *= 10;
1055 }
1056 g.doRound(drops, "Number::operator rep() rounding overflow");
1057 }
1058 return drops;
1059}
1060
1061Number
1062Number::truncate() const noexcept
1063{
1064 if (exponent_ >= 0 || mantissa_ == 0)
1065 return *this;
1066
1067 Number ret = *this;
1068 while (ret.exponent_ < 0 && ret.mantissa_ != 0)
1069 {
1070 ret.exponent_ += 1;
1071 ret.mantissa_ /= rep(10);
1072 }
1073 // We are guaranteed that normalize() will never throw an exception
1074 // because exponent is either negative or zero at this point.
1075 ret.normalize(kRange);
1076 return ret;
1077}
1078
1080to_string(Number const& amount)
1081{
1082 // keep full internal accuracy, but make more human friendly if possible
1083 static constexpr Number kZero = Number{};
1084 if (amount == kZero)
1085 return "0";
1086
1087 auto exponent = amount.exponent_;
1088 auto mantissa = amount.mantissa_;
1089 bool const negative = amount.negative_;
1090
1091 // Use scientific notation for exponents that are too small or too large
1092 auto const rangeLog = Number::mantissaLog();
1093 if (((exponent != 0) && ((exponent < -(rangeLog + 10)) || (exponent > -(rangeLog - 10)))))
1094 {
1095 while (mantissa != 0 && mantissa % 10 == 0 && exponent < Number::kMaxExponent)
1096 {
1097 mantissa /= 10;
1098 ++exponent;
1099 }
1100 std::string ret = negative ? "-" : "";
1102 ret.append(1, 'e');
1104 return ret;
1105 }
1106
1107 XRPL_ASSERT(exponent + 43 > 0, "xrpl::to_string(Number) : minimum exponent");
1108
1109 ptrdiff_t const padPrefix = rangeLog + 12;
1110 ptrdiff_t const padSuffix = rangeLog + 8;
1111
1112 std::string const rawValue(std::to_string(mantissa));
1113 std::string val;
1114
1115 val.reserve(rawValue.length() + padPrefix + padSuffix);
1116 val.append(padPrefix, '0');
1117 val.append(rawValue);
1118 val.append(padSuffix, '0');
1119
1120 ptrdiff_t const offset(exponent + padPrefix + rangeLog + 1);
1121
1122 auto preFrom(val.begin());
1123 auto const preTo(val.begin() + offset);
1124
1125 auto const postFrom(val.begin() + offset);
1126 auto postTo(val.end());
1127
1128 // Crop leading zeroes. Take advantage of the fact that there's always a
1129 // fixed amount of leading zeroes and skip them.
1130 if (std::distance(preFrom, preTo) > padPrefix)
1131 preFrom += padPrefix;
1132
1133 XRPL_ASSERT(postTo >= postFrom, "xrpl::to_string(Number) : first distance check");
1134
1135 preFrom = std::find_if(preFrom, preTo, [](char c) { return c != '0'; });
1136
1137 // Crop trailing zeroes. Take advantage of the fact that there's always a
1138 // fixed amount of trailing zeroes and skip them.
1139 if (std::distance(postFrom, postTo) > padSuffix)
1140 postTo -= padSuffix;
1141
1142 XRPL_ASSERT(postTo >= postFrom, "xrpl::to_string(Number) : second distance check");
1143
1144 postTo = std::find_if(
1147 [](char c) { return c != '0'; })
1148 .base();
1149
1150 std::string ret;
1151
1152 if (negative)
1153 ret.append(1, '-');
1154
1155 // Assemble the output:
1156 if (preFrom == preTo)
1157 {
1158 ret.append(1, '0');
1159 }
1160 else
1161 {
1162 ret.append(preFrom, preTo);
1163 }
1164
1165 if (postTo != postFrom)
1166 {
1167 ret.append(1, '.');
1168 ret.append(postFrom, postTo);
1169 }
1170
1171 return ret;
1172}
1173
1174// Returns f^n
1175// Uses a log_2(n) number of multiplications
1176
1177Number
1178power(Number const& f, unsigned n)
1179{
1180 if (n == 0)
1181 return Number::one();
1182 if (n == 1)
1183 return f;
1184 auto r = power(f, n / 2);
1185 r *= r;
1186 if (n % 2 != 0)
1187 r *= f;
1188 return r;
1189}
1190
1191// Returns f^(1/d)
1192// Uses Newton–Raphson iterations until the result stops changing
1193// to find the non-negative root of the polynomial g(x) = x^d - f
1194
1195// This function, and power(Number f, unsigned n, unsigned d)
1196// treat corner cases such as 0 roots as advised by Annex F of
1197// the C standard, which itself is consistent with the IEEE
1198// floating point standards.
1199
1200Number
1201root(Number f, unsigned d)
1202{
1203 static constexpr Number kZero = Number{};
1204 auto const one = Number::one();
1205
1206 if (f == one || d == 1)
1207 return f;
1208 if (d == 0)
1209 {
1210 if (f == -one)
1211 return one;
1212 if (abs(f) < one)
1213 return kZero;
1214 throw std::overflow_error("Number::root infinity");
1215 }
1216 if (f < kZero && d % 2 == 0)
1217 throw std::overflow_error("Number::root nan");
1218 if (f == kZero)
1219 return f;
1220
1221 // Scale f into the range (0, 1) such that f's exponent is a multiple of d
1222 auto e = f.exponent_ + Number::mantissaLog() + 1;
1223 auto const di = static_cast<int>(d);
1224 auto ex = [e = e, di = di]() // Euclidean remainder of e/d
1225 {
1226 int const k = (e >= 0 ? e : e - (di - 1)) / di;
1227 int const k2 = e - (k * di);
1228 if (k2 == 0)
1229 return 0;
1230 return di - k2;
1231 }();
1232 e += ex;
1233 f = f.shiftExponent(-e); // f /= 10^e;
1234
1235 XRPL_ASSERT_PARTS(f.isnormal(), "xrpl::root(Number, unsigned)", "f is normalized");
1236 bool neg = false;
1237 if (f < kZero)
1238 {
1239 neg = true;
1240 f = -f;
1241 }
1242
1243 // Quadratic least squares curve fit of f^(1/d) in the range [0, 1]
1244
1245 // NOLINTNEXTLINE(readability-identifier-naming)
1246 auto const D = (((((6 * di) + 11) * di) + 6) * di) + 1;
1247 auto const a0 = 3 * di * ((((2 * di) - 3) * di) + 1);
1248 auto const a1 = 24 * di * ((2 * di) - 1);
1249 auto const a2 = -30 * (di - 1) * di;
1250 Number r = ((Number{a2} * f + Number{a1}) * f + Number{a0}) / Number{D};
1251 if (neg)
1252 {
1253 f = -f;
1254 r = -r;
1255 }
1256
1257 // Newton–Raphson iteration of f^(1/d) with initial guess r
1258 // halt when r stops changing, checking for bouncing on the last iteration
1259 Number rm1{};
1260 Number rm2{};
1261 do
1262 {
1263 rm2 = rm1;
1264 rm1 = r;
1265 r = (Number(d - 1) * r + f / power(r, d - 1)) / Number(d);
1266 } while (r != rm1 && r != rm2);
1267
1268 // return r * 10^(e/d) to reverse scaling
1269 auto const result = r.shiftExponent(e / di);
1270 XRPL_ASSERT_PARTS(result.isnormal(), "xrpl::root(Number, unsigned)", "result is normalized");
1271 return result;
1272}
1273
1274Number
1276{
1277 static constexpr Number kZero = Number{};
1278 auto const one = Number::one();
1279
1280 if (f == one)
1281 return f;
1282 if (f < kZero)
1283 throw std::overflow_error("Number::root nan");
1284 if (f == kZero)
1285 return f;
1286
1287 // Scale f into the range (0, 1) such that f's exponent is a multiple of d
1288 auto e = f.exponent_ + Number::mantissaLog() + 1;
1289 if (e % 2 != 0)
1290 ++e;
1291 f = f.shiftExponent(-e); // f /= 10^e;
1292 XRPL_ASSERT_PARTS(f.isnormal(), "xrpl::root2(Number)", "f is normalized");
1293
1294 // Quadratic least squares curve fit of f^(1/d) in the range [0, 1]
1295 auto const D = 105; // NOLINT(readability-identifier-naming)
1296 auto const a0 = 18;
1297 auto const a1 = 144;
1298 auto const a2 = -60;
1299 Number r = ((Number{a2} * f + Number{a1}) * f + Number{a0}) / Number{D};
1300
1301 // Newton–Raphson iteration of f^(1/2) with initial guess r
1302 // halt when r stops changing, checking for bouncing on the last iteration
1303 Number rm1{};
1304 Number rm2{};
1305 do
1306 {
1307 rm2 = rm1;
1308 rm1 = r;
1309 r = (r + f / r) / Number(2);
1310 } while (r != rm1 && r != rm2);
1311
1312 // return r * 10^(e/2) to reverse scaling
1313 auto const result = r.shiftExponent(e / 2);
1314 XRPL_ASSERT_PARTS(result.isnormal(), "xrpl::root2(Number)", "result is normalized");
1315
1316 return result;
1317}
1318
1319// Returns f^(n/d)
1320
1321Number
1322power(Number const& f, unsigned n, unsigned d)
1323{
1324 static constexpr Number kZero = Number{};
1325 auto const one = Number::one();
1326
1327 if (f == one)
1328 return f;
1329 auto g = std::gcd(n, d);
1330 if (g == 0)
1331 throw std::overflow_error("Number::power nan");
1332 if (d == 0)
1333 {
1334 if (f == -one)
1335 return one;
1336 if (abs(f) < one)
1337 return kZero;
1338 // abs(f) > one
1339 throw std::overflow_error("Number::power infinity");
1340 }
1341 if (n == 0)
1342 return one;
1343 n /= g;
1344 d /= g;
1345 if ((n % 2) == 1 && (d % 2) == 0 && f < kZero)
1346 throw std::overflow_error("Number::power nan");
1347 return root(power(f, n), d);
1348}
1349
1350} // namespace xrpl
T append(T... args)
T begin(T... args)
bool isNegative() const noexcept
Definition Number.cpp:264
void setPositive() noexcept
Definition Number.cpp:246
void setDropped() noexcept
Definition Number.cpp:258
unsigned pop() noexcept
Definition Number.cpp:285
void setNegative() noexcept
Definition Number.cpp:252
void bringIntoRange(bool &negative, T &mantissa, int &exponent, internalrep const &minMantissa)
Definition Number.cpp:356
void doDropDigit(T &mantissa, int &exponent) noexcept
Drop a digit from the mantissa, and increment the exponent, storing the dropped digit in this Guard.
Definition Number.cpp:294
void doRoundDown(bool &negative, T &mantissa, int &exponent, internalrep const &minMantissa)
Definition Number.cpp:450
int round() const noexcept
Definition Number.cpp:318
void doPush(unsigned d) noexcept
Definition Number.cpp:270
std::uint8_t xbit_
Definition Number.cpp:170
void doRoundUp(bool &negative, T &mantissa, int &exponent, internalrep const &minMantissa, internalrep const &maxMantissa, MantissaRange::CuspRoundingFix cuspRoundingFixEnabled, std::string location)
Definition Number.cpp:381
std::uint8_t sbit_
Definition Number.cpp:171
void doRound(rep &drops, std::string location) const
Definition Number.cpp:471
void push(T d) noexcept
Definition Number.cpp:279
std::uint64_t digits_
Definition Number.cpp:169
Number is a floating point type that can represent a wide range of values.
Definition Number.h:306
internalrep mantissa_
Definition Number.h:311
static internalrep minMantissa()
Definition Number.h:516
constexpr rep mantissa() const noexcept
Returns the mantissa of the external view of the Number.
Definition Number.h:640
Number & operator/=(Number const &x)
Definition Number.cpp:854
Number & operator+=(Number const &x)
Definition Number.cpp:691
Number truncate() const noexcept
Definition Number.cpp:1062
std::int64_t rep
Definition Number.h:307
friend std::string to_string(Number const &amount)
Definition Number.cpp:1080
static constexpr int kMinExponent
Definition Number.h:316
static RoundingMode setround(RoundingMode inMode)
Definition Number.cpp:111
static RoundingMode mode
Definition Number.h:545
MantissaRange::rep internalrep
Definition Number.h:308
static RoundingMode getround()
Definition Number.cpp:105
static std::reference_wrapper< MantissaRange const > kRange
Definition Number.h:551
static constexpr internalrep kMaxRep
Definition Number.h:319
Number shiftExponent(int exponentDelta) const
Definition Number.cpp:675
static MantissaRange::MantissaScale getMantissaScale()
Returns which mantissa scale is currently in use for normalization.
Definition Number.cpp:117
static internalrep externalToInternal(rep mantissa)
Definition Number.cpp:500
static internalrep maxMantissa()
Definition Number.h:522
static constexpr int kMaxExponent
Definition Number.h:317
bool isnormal() const noexcept
Definition Number.h:778
constexpr int exponent() const noexcept
Returns the exponent of the external view of the Number.
Definition Number.h:661
friend void doNormalize(bool &negative, T &mantissa, int &exponent, MantissaRange::rep const &minMantissa, MantissaRange::rep const &maxMantissa, MantissaRange::CuspRoundingFix cuspRoundingFixEnabled, bool dropped)
Definition Number.cpp:527
friend Number root2(Number f)
Definition Number.cpp:1275
int exponent_
Definition Number.h:312
void normalize(MantissaRange const &range)
Definition Number.cpp:666
static Number one()
Definition Number.cpp:519
Number & operator*=(Number const &x)
Definition Number.cpp:792
constexpr Number()=default
static void setMantissaScale(MantissaRange::MantissaScale scale)
Changes which mantissa scale is used for normalization.
Definition Number.cpp:123
bool negative_
Definition Number.h:310
static int mantissaLog()
Definition Number.h:528
friend Number root(Number f, unsigned d)
Definition Number.cpp:1201
T distance(T... args)
T emplace(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:34
int scale(Number const &number, Asset const &asset)
Get the scale of a Number for a given asset.
Definition STAmount.h:779
Number power(Number const &f, unsigned n)
Definition Number.cpp:1178
void logicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
constexpr std::array< std::uint64_t, detail::kInt64Digits > kPowerOfTen
Definition Number.h:78
constexpr bool isPowerOfTen(T value)
Definition Number.h:40
constexpr Number abs(Number x) noexcept
Definition Number.h:823
static unsigned divu10(uint128_t &u)
Definition Number.cpp:137
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:49
T reserve(T... args)
T length(T... args)
MantissaRange defines a range for the mantissa of a normalized Number.
Definition Number.h:120
rep const min
Definition Number.h:142
MantissaScale const scale
Definition Number.h:140
static MantissaRange const & getMantissaRange(MantissaScale scale)
Definition Number.cpp:99
std::uint64_t rep
Definition Number.h:121
static std::set< MantissaScale > const & getAllScales()
Definition Number.cpp:37
int const log
Definition Number.h:141
CuspRoundingFix const cuspRoundingFixEnabled
Definition Number.h:144
static std::unordered_map< MantissaScale, MantissaRange > const & getRanges()
Definition Number.cpp:48
constexpr MantissaRange(MantissaScale sc)
Definition Number.h:136
rep const max
Definition Number.h:143
T to_string(T... args)