rippled
Loading...
Searching...
No Matches
Number.cpp
1#include <xrpl/basics/Number.h>
2// Keep Number.h first to ensure it can build without hidden dependencies
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 <iterator>
10#include <limits>
11#include <numeric>
12#include <stdexcept>
13#include <string>
14#include <type_traits>
15#include <utility>
16
17#ifdef _MSC_VER
18#pragma message("Using boost::multiprecision::uint128_t and int128_t")
19#include <boost/multiprecision/cpp_int.hpp>
20using uint128_t = boost::multiprecision::uint128_t;
21using int128_t = boost::multiprecision::int128_t;
22#else // !defined(_MSC_VER)
23using uint128_t = __uint128_t;
24using int128_t = __int128_t;
25#endif // !defined(_MSC_VER)
26
27namespace xrpl {
28
31 largeRange;
32
35{
36 return mode_;
37}
38
41{
42 return std::exchange(mode_, mode);
43}
44
47{
48 return range_.get().scale;
49}
50
51void
53{
54 if (scale != MantissaRange::small && scale != MantissaRange::large)
55 LogicError("Unknown mantissa scale");
57}
58
59// Guard
60
61// The Guard class is used to temporarily add extra digits of
62// precision to an operation. This enables the final result
63// to be correctly rounded to the internal precision of Number.
64
65template <class T>
68
70{
71 std::uint64_t digits_; // 16 decimal guard digits
72 std::uint8_t xbit_ : 1; // has a non-zero digit been shifted off the end
73 std::uint8_t sbit_ : 1; // the sign of the guard digits
74
75public:
76 explicit Guard() : digits_{0}, xbit_{0}, sbit_{0}
77 {
78 }
79
80 // set & test the sign bit
81 void
82 set_positive() noexcept;
83 void
84 set_negative() noexcept;
85 bool
86 is_negative() const noexcept;
87
88 // add a digit
89 template <class T>
90 void
91 push(T d) noexcept;
92
93 // recover a digit
94 unsigned
95 pop() noexcept;
96
97 // Indicate round direction: 1 is up, -1 is down, 0 is even
98 // This enables the client to round towards nearest, and on
99 // tie, round towards even.
100 int
101 round() noexcept;
102
103 // Modify the result to the correctly rounded value
104 template <UnsignedMantissa T>
105 void
106 doRoundUp(
107 bool& negative,
108 T& mantissa,
109 int& exponent,
112 std::string location);
113
114 // Modify the result to the correctly rounded value
115 template <UnsignedMantissa T>
116 void
118 bool& negative,
119 T& mantissa,
120 int& exponent,
121 internalrep const& minMantissa);
122
123 // Modify the result to the correctly rounded value
124 void
125 doRound(rep& drops, std::string location);
126
127private:
128 void
129 doPush(unsigned d) noexcept;
130
131 template <UnsignedMantissa T>
132 void
134 bool& negative,
135 T& mantissa,
136 int& exponent,
137 internalrep const& minMantissa);
138};
139
140inline void
142{
143 sbit_ = 0;
144}
145
146inline void
148{
149 sbit_ = 1;
150}
151
152inline bool
154{
155 return sbit_ == 1;
156}
157
158inline void
159Number::Guard::doPush(unsigned d) noexcept
160{
161 xbit_ = xbit_ || ((digits_ & 0x0000'0000'0000'000F) != 0);
162 digits_ >>= 4;
163 digits_ |= (d & 0x0000'0000'0000'000FULL) << 60;
164}
165
166template <class T>
167inline void
169{
170 doPush(static_cast<unsigned>(d));
171}
172
173inline unsigned
175{
176 unsigned d = (digits_ & 0xF000'0000'0000'0000) >> 60;
177 digits_ <<= 4;
178 return d;
179}
180
181// Returns:
182// -1 if Guard is less than half
183// 0 if Guard is exactly half
184// 1 if Guard is greater than half
185int
187{
188 auto mode = Number::getround();
189
190 if (mode == towards_zero)
191 return -1;
192
193 if (mode == downward)
194 {
195 if (sbit_)
196 {
197 if (digits_ > 0 || xbit_)
198 return 1;
199 }
200 return -1;
201 }
202
203 if (mode == upward)
204 {
205 if (sbit_)
206 return -1;
207 if (digits_ > 0 || xbit_)
208 return 1;
209 return -1;
210 }
211
212 // assume round to nearest if mode is not one of the predefined values
213 if (digits_ > 0x5000'0000'0000'0000)
214 return 1;
215 if (digits_ < 0x5000'0000'0000'0000)
216 return -1;
217 if (xbit_)
218 return 1;
219 return 0;
220}
221
222template <UnsignedMantissa T>
223void
225 bool& negative,
226 T& mantissa,
227 int& exponent,
229{
230 // Bring mantissa back into the minMantissa / maxMantissa range AFTER
231 // rounding
232 if (mantissa < minMantissa)
233 {
234 mantissa *= 10;
235 --exponent;
236 }
237 if (exponent < minExponent)
238 {
239 constexpr Number zero = Number{};
240
241 negative = zero.negative_;
242 mantissa = zero.mantissa_;
243 exponent = zero.exponent_;
244 }
245}
246
247template <UnsignedMantissa T>
248void
250 bool& negative,
251 T& mantissa,
252 int& exponent,
255 std::string location)
256{
257 auto r = round();
258 if (r == 1 || (r == 0 && (mantissa & 1) == 1))
259 {
260 ++mantissa;
261 // Ensure mantissa after incrementing fits within both the
262 // min/maxMantissa range and is a valid "rep".
264 {
265 mantissa /= 10;
266 ++exponent;
267 }
268 }
270 if (exponent > maxExponent)
271 throw std::overflow_error(location);
272}
273
274template <UnsignedMantissa T>
275void
277 bool& negative,
278 T& mantissa,
279 int& exponent,
281{
282 auto r = round();
283 if (r == 1 || (r == 0 && (mantissa & 1) == 1))
284 {
285 --mantissa;
286 if (mantissa < minMantissa)
287 {
288 mantissa *= 10;
289 --exponent;
290 }
291 }
293}
294
295// Modify the result to the correctly rounded value
296void
298{
299 auto r = round();
300 if (r == 1 || (r == 0 && (drops & 1) == 1))
301 {
302 if (drops >= maxRep)
303 {
304 static_assert(sizeof(internalrep) == sizeof(rep));
305 // This should be impossible, because it's impossible to represent
306 // "maxRep + 0.6" in Number, regardless of the scale. There aren't
307 // enough digits available. You'd either get a mantissa of "maxRep"
308 // or "(maxRep + 1) / 10", neither of which will round up when
309 // converting to rep, though the latter might overflow _before_
310 // rounding.
311 throw std::overflow_error(location); // LCOV_EXCL_LINE
312 }
313 ++drops;
314 }
315 if (is_negative())
316 drops = -drops;
317}
318
319// Number
320
321// Safely convert rep (int64) mantissa to internalrep (uint64). If the rep is
322// negative, returns the positive value. This takes a little extra work because
323// converting std::numeric_limits<std::int64_t>::min() flirts with UB, and can
324// vary across compilers.
327{
328 // If the mantissa is already positive, just return it
329 if (mantissa >= 0)
330 return mantissa;
331 // If the mantissa is negative, but fits within the positive range of rep,
332 // return it negated
334 return -mantissa;
335
336 // If the mantissa doesn't fit within the positive range, convert to
337 // int128_t, negate that, and cast it back down to the internalrep
338 // In practice, this is only going to cover the case of
339 // std::numeric_limits<rep>::min().
340 int128_t temp = mantissa;
341 return static_cast<internalrep>(-temp);
342}
343
344constexpr Number
346{
347 return Number{
348 false,
352};
353
355
356constexpr Number
358{
359 return Number{
360 false,
364};
365
367
368Number
370{
371 if (&range_.get() == &smallRange)
372 return oneSml;
373 XRPL_ASSERT(&range_.get() == &largeRange, "Number::one() : valid range_");
374 return oneLrg;
375}
376
377// Use the member names in this static function for now so the diff is cleaner
378// TODO: Rename the function parameters to get rid of the "_" suffix
379template <class T>
380void
382 bool& negative,
383 T& mantissa_,
384 int& exponent_,
387{
388 auto constexpr minExponent = Number::minExponent;
389 auto constexpr maxExponent = Number::maxExponent;
390 auto constexpr maxRep = Number::maxRep;
391
392 using Guard = Number::Guard;
393
394 constexpr Number zero = Number{};
395 if (mantissa_ == 0)
396 {
397 mantissa_ = zero.mantissa_;
398 exponent_ = zero.exponent_;
399 negative = zero.negative_;
400 return;
401 }
402 auto m = mantissa_;
403 while ((m < minMantissa) && (exponent_ > minExponent))
404 {
405 m *= 10;
406 --exponent_;
407 }
408 Guard g;
409 if (negative)
410 g.set_negative();
411 while (m > maxMantissa)
412 {
413 if (exponent_ >= maxExponent)
414 throw std::overflow_error("Number::normalize 1");
415 g.push(m % 10);
416 m /= 10;
417 ++exponent_;
418 }
419 if ((exponent_ < minExponent) || (m < minMantissa))
420 {
421 mantissa_ = zero.mantissa_;
422 exponent_ = zero.exponent_;
423 negative = zero.negative_;
424 return;
425 }
426
427 // When using the largeRange, "m" needs fit within an int64, even if
428 // the final mantissa_ is going to end up larger to fit within the
429 // MantissaRange. Cut it down here so that the rounding will be done while
430 // it's smaller.
431 //
432 // Example: 9,900,000,000,000,123,456 > 9,223,372,036,854,775,807,
433 // so "m" will be modified to 990,000,000,000,012,345. Then that value
434 // will be rounded to 990,000,000,000,012,345 or
435 // 990,000,000,000,012,346, depending on the rounding mode. Finally,
436 // mantissa_ will be "m*10" so it fits within the range, and end up as
437 // 9,900,000,000,000,123,450 or 9,900,000,000,000,123,460.
438 // mantissa() will return mantissa_ / 10, and exponent() will return
439 // exponent_ + 1.
440 if (m > maxRep)
441 {
442 if (exponent_ >= maxExponent)
443 throw std::overflow_error("Number::normalize 1.5");
444 g.push(m % 10);
445 m /= 10;
446 ++exponent_;
447 }
448 // Before modification, m should be within the min/max range. After
449 // modification, it must be less than maxRep. In other words, the original
450 // value should have been no more than maxRep * 10.
451 // (maxRep * 10 > maxMantissa)
452 XRPL_ASSERT_PARTS(
453 m <= maxRep,
454 "xrpl::doNormalize",
455 "intermediate mantissa fits in int64");
456 mantissa_ = m;
457
458 g.doRoundUp(
459 negative,
460 mantissa_,
461 exponent_,
464 "Number::normalize 2");
465 XRPL_ASSERT_PARTS(
467 "xrpl::doNormalize",
468 "final mantissa fits in range");
469}
470
471template <>
472void
473Number::normalize<uint128_t>(
474 bool& negative,
475 uint128_t& mantissa,
476 int& exponent,
479{
481}
482
483template <>
484void
485Number::normalize<unsigned long long>(
486 bool& negative,
487 unsigned long long& mantissa,
488 int& exponent,
491{
493}
494
495template <>
496void
497Number::normalize<unsigned long>(
498 bool& negative,
499 unsigned long& mantissa,
500 int& exponent,
503{
505}
506
507void
509{
510 auto const& range = range_.get();
512}
513
514// Copy the number, but set a new exponent. Because the mantissa doesn't change,
515// the result will be "mostly" normalized, but the exponent could go out of
516// range.
517Number
518Number::shiftExponent(int exponentDelta) const
519{
520 XRPL_ASSERT_PARTS(isnormal(), "xrpl::Number::shiftExponent", "normalized");
521 auto const newExponent = exponent_ + exponentDelta;
522 if (newExponent >= maxExponent)
523 throw std::overflow_error("Number::shiftExponent");
524 if (newExponent < minExponent)
525 {
526 return Number{};
527 }
528 Number const result{negative_, mantissa_, newExponent, unchecked{}};
529 XRPL_ASSERT_PARTS(
530 result.isnormal(),
531 "xrpl::Number::shiftExponent",
532 "result is normalized");
533 return result;
534}
535
536Number&
538{
539 constexpr Number zero = Number{};
540 if (y == zero)
541 return *this;
542 if (*this == zero)
543 {
544 *this = y;
545 return *this;
546 }
547 if (*this == -y)
548 {
549 *this = zero;
550 return *this;
551 }
552
553 XRPL_ASSERT(
554 isnormal() && y.isnormal(),
555 "xrpl::Number::operator+=(Number) : is normal");
556 // *n = negative
557 // *s = sign
558 // *m = mantissa
559 // *e = exponent
560
561 // Need to use uint128_t, because large mantissas can overflow when added
562 // together.
563 bool xn = negative_;
564 uint128_t xm = mantissa_;
565 auto xe = exponent_;
566
567 bool yn = y.negative_;
568 uint128_t ym = y.mantissa_;
569 auto ye = y.exponent_;
570 Guard g;
571 if (xe < ye)
572 {
573 if (xn)
574 g.set_negative();
575 do
576 {
577 g.push(xm % 10);
578 xm /= 10;
579 ++xe;
580 } while (xe < ye);
581 }
582 else if (xe > ye)
583 {
584 if (yn)
585 g.set_negative();
586 do
587 {
588 g.push(ym % 10);
589 ym /= 10;
590 ++ye;
591 } while (xe > ye);
592 }
593
594 auto const& range = range_.get();
595 auto const& minMantissa = range.min;
596 auto const& maxMantissa = range.max;
597
598 if (xn == yn)
599 {
600 xm += ym;
601 if (xm > maxMantissa || xm > maxRep)
602 {
603 g.push(xm % 10);
604 xm /= 10;
605 ++xe;
606 }
607 g.doRoundUp(
608 xn, xm, xe, minMantissa, maxMantissa, "Number::addition overflow");
609 }
610 else
611 {
612 if (xm > ym)
613 {
614 xm = xm - ym;
615 }
616 else
617 {
618 xm = ym - xm;
619 xe = ye;
620 xn = yn;
621 }
622 while (xm < minMantissa && xm * 10 <= maxRep)
623 {
624 xm *= 10;
625 xm -= g.pop();
626 --xe;
627 }
628 g.doRoundDown(xn, xm, xe, minMantissa);
629 }
630
631 negative_ = xn;
632 mantissa_ = static_cast<internalrep>(xm);
633 exponent_ = xe;
634 normalize();
635 return *this;
636}
637
638// Optimization equivalent to:
639// auto r = static_cast<unsigned>(u % 10);
640// u /= 10;
641// return r;
642// Derived from Hacker's Delight Second Edition Chapter 10
643// by Henry S. Warren, Jr.
644static inline unsigned
645divu10(uint128_t& u)
646{
647 // q = u * 0.75
648 auto q = (u >> 1) + (u >> 2);
649 // iterate towards q = u * 0.8
650 q += q >> 4;
651 q += q >> 8;
652 q += q >> 16;
653 q += q >> 32;
654 q += q >> 64;
655 // q /= 8 approximately == u / 10
656 q >>= 3;
657 // r = u - q * 10 approximately == u % 10
658 auto r = static_cast<unsigned>(u - ((q << 3) + (q << 1)));
659 // correction c is 1 if r >= 10 else 0
660 auto c = (r + 6) >> 4;
661 u = q + c;
662 r -= c * 10;
663 return r;
664}
665
666Number&
668{
669 constexpr Number zero = Number{};
670 if (*this == zero)
671 return *this;
672 if (y == zero)
673 {
674 *this = y;
675 return *this;
676 }
677 // *n = negative
678 // *s = sign
679 // *m = mantissa
680 // *e = exponent
681
682 bool xn = negative_;
683 int xs = xn ? -1 : 1;
685 auto xe = exponent_;
686
687 bool yn = y.negative_;
688 int ys = yn ? -1 : 1;
689 internalrep ym = y.mantissa_;
690 auto ye = y.exponent_;
691
692 auto zm = uint128_t(xm) * uint128_t(ym);
693 auto ze = xe + ye;
694 auto zs = xs * ys;
695 bool zn = (zs == -1);
696 Guard g;
697 if (zn)
698 g.set_negative();
699
700 auto const& range = range_.get();
701 auto const& minMantissa = range.min;
702 auto const& maxMantissa = range.max;
703
704 while (zm > maxMantissa || zm > maxRep)
705 {
706 // The following is optimization for:
707 // g.push(static_cast<unsigned>(zm % 10));
708 // zm /= 10;
709 g.push(divu10(zm));
710 ++ze;
711 }
712 xm = static_cast<internalrep>(zm);
713 xe = ze;
714 g.doRoundUp(
715 zn,
716 xm,
717 xe,
720 "Number::multiplication overflow : exponent is " + std::to_string(xe));
721 negative_ = zn;
722 mantissa_ = xm;
723 exponent_ = xe;
724
725 normalize();
726 return *this;
727}
728
729Number&
731{
732 constexpr Number zero = Number{};
733 if (y == zero)
734 throw std::overflow_error("Number: divide by 0");
735 if (*this == zero)
736 return *this;
737 // n* = numerator
738 // d* = denominator
739 // *p = negative (positive?)
740 // *s = sign
741 // *m = mantissa
742 // *e = exponent
743
744 bool np = negative_;
745 int ns = (np ? -1 : 1);
746 auto nm = mantissa_;
747 auto ne = exponent_;
748
749 bool dp = y.negative_;
750 int ds = (dp ? -1 : 1);
751 auto dm = y.mantissa_;
752 auto de = y.exponent_;
753
754 auto const& range = range_.get();
755 auto const& minMantissa = range.min;
756 auto const& maxMantissa = range.max;
757
758 // Shift by 10^17 gives greatest precision while not overflowing
759 // uint128_t or the cast back to int64_t
760 // TODO: Can/should this be made bigger for largeRange?
761 // log(2^128,10) ~ 38.5
762 // largeRange.log = 18, fits in 10^19
763 // f can be up to 10^(38-19) = 10^19 safely
764 static_assert(smallRange.log == 15);
765 static_assert(largeRange.log == 18);
767 uint128_t const f =
768 small ? 100'000'000'000'000'000 : 10'000'000'000'000'000'000ULL;
769 XRPL_ASSERT_PARTS(
770 f >= minMantissa * 10, "Number::operator/=", "factor expected size");
771
772 // unsigned denominator
773 auto const dmu = static_cast<uint128_t>(dm);
774 // correctionFactor can be anything between 10 and f, depending on how much
775 // extra precision we want to only use for rounding with the
776 // largeRange. Three digits seems like plenty, and is more than
777 // the smallRange uses.
778 uint128_t const correctionFactor = 1'000;
779
780 auto const numerator = uint128_t(nm) * f;
781
782 auto zm = numerator / dmu;
783 auto ze = ne - de - (small ? 17 : 19);
784 bool zn = (ns * ds) < 0;
785 if (!small)
786 {
787 // Virtually multiply numerator by correctionFactor. Since that would
788 // overflow in the existing uint128_t, we'll do that part separately.
789 // The math for this would work for small mantissas, but we need to
790 // preserve existing behavior.
791 //
792 // Consider:
793 // ((numerator * correctionFactor) / dmu) / correctionFactor
794 // = ((numerator / dmu) * correctionFactor) / correctionFactor)
795 //
796 // But that assumes infinite precision. With integer math, this is
797 // equivalent to
798 //
799 // = ((numerator / dmu * correctionFactor)
800 // + ((numerator % dmu) * correctionFactor) / dmu) / correctionFactor
801 //
802 // We have already set `mantissa_ = numerator / dmu`. Now we
803 // compute `remainder = numerator % dmu`, and if it is
804 // nonzero, we do the rest of the arithmetic. If it's zero, we can skip
805 // it.
806 auto const remainder = (numerator % dmu);
807 if (remainder != 0)
808 {
809 zm *= correctionFactor;
810 auto const correction = remainder * correctionFactor / dmu;
811 zm += correction;
812 // divide by 1000 by moving the exponent, so we don't lose the
813 // integer value we just computed
814 ze -= 3;
815 }
816 }
817 normalize(zn, zm, ze, minMantissa, maxMantissa);
818 negative_ = zn;
819 mantissa_ = static_cast<internalrep>(zm);
820 exponent_ = ze;
821 XRPL_ASSERT_PARTS(
822 isnormal(), "xrpl::Number::operator/=", "result is normalized");
823
824 return *this;
825}
826
827Number::operator rep() const
828{
829 rep drops = mantissa();
830 int offset = exponent();
831 Guard g;
832 if (drops != 0)
833 {
834 if (negative_)
835 {
836 g.set_negative();
837 drops = -drops;
838 }
839 for (; offset < 0; ++offset)
840 {
841 g.push(drops % 10);
842 drops /= 10;
843 }
844 for (; offset > 0; --offset)
845 {
846 if (drops > maxRep / 10)
847 throw std::overflow_error("Number::operator rep() overflow");
848 drops *= 10;
849 }
850 g.doRound(drops, "Number::operator rep() rounding overflow");
851 }
852 return drops;
853}
854
855Number
856Number::truncate() const noexcept
857{
858 if (exponent_ >= 0 || mantissa_ == 0)
859 return *this;
860
861 Number ret = *this;
862 while (ret.exponent_ < 0 && ret.mantissa_ != 0)
863 {
864 ret.exponent_ += 1;
865 ret.mantissa_ /= rep(10);
866 }
867 // We are guaranteed that normalize() will never throw an exception
868 // because exponent is either negative or zero at this point.
869 ret.normalize();
870 return ret;
871}
872
874to_string(Number const& amount)
875{
876 // keep full internal accuracy, but make more human friendly if possible
877 constexpr Number zero = Number{};
878 if (amount == zero)
879 return "0";
880
881 auto exponent = amount.exponent_;
882 auto mantissa = amount.mantissa_;
883 bool const negative = amount.negative_;
884
885 // Use scientific notation for exponents that are too small or too large
886 auto const rangeLog = Number::mantissaLog();
887 if (((exponent != 0) &&
888 ((exponent < -(rangeLog + 10)) || (exponent > -(rangeLog - 10)))))
889 {
890 while (mantissa != 0 && mantissa % 10 == 0 &&
892 {
893 mantissa /= 10;
894 ++exponent;
895 }
896 std::string ret = negative ? "-" : "";
898 ret.append(1, 'e');
900 return ret;
901 }
902
903 XRPL_ASSERT(
904 exponent + 43 > 0, "xrpl::to_string(Number) : minimum exponent");
905
906 ptrdiff_t const pad_prefix = rangeLog + 12;
907 ptrdiff_t const pad_suffix = rangeLog + 8;
908
909 std::string const raw_value(std::to_string(mantissa));
910 std::string val;
911
912 val.reserve(raw_value.length() + pad_prefix + pad_suffix);
913 val.append(pad_prefix, '0');
914 val.append(raw_value);
915 val.append(pad_suffix, '0');
916
917 ptrdiff_t const offset(exponent + pad_prefix + rangeLog + 1);
918
919 auto pre_from(val.begin());
920 auto const pre_to(val.begin() + offset);
921
922 auto const post_from(val.begin() + offset);
923 auto post_to(val.end());
924
925 // Crop leading zeroes. Take advantage of the fact that there's always a
926 // fixed amount of leading zeroes and skip them.
927 if (std::distance(pre_from, pre_to) > pad_prefix)
928 pre_from += pad_prefix;
929
930 XRPL_ASSERT(
931 post_to >= post_from, "xrpl::to_string(Number) : first distance check");
932
933 pre_from = std::find_if(pre_from, pre_to, [](char c) { return c != '0'; });
934
935 // Crop trailing zeroes. Take advantage of the fact that there's always a
936 // fixed amount of trailing zeroes and skip them.
937 if (std::distance(post_from, post_to) > pad_suffix)
938 post_to -= pad_suffix;
939
940 XRPL_ASSERT(
941 post_to >= post_from,
942 "xrpl::to_string(Number) : second distance check");
943
944 post_to = std::find_if(
947 [](char c) { return c != '0'; })
948 .base();
949
950 std::string ret;
951
952 if (negative)
953 ret.append(1, '-');
954
955 // Assemble the output:
956 if (pre_from == pre_to)
957 ret.append(1, '0');
958 else
959 ret.append(pre_from, pre_to);
960
961 if (post_to != post_from)
962 {
963 ret.append(1, '.');
964 ret.append(post_from, post_to);
965 }
966
967 return ret;
968}
969
970// Returns f^n
971// Uses a log_2(n) number of multiplications
972
973Number
974power(Number const& f, unsigned n)
975{
976 if (n == 0)
977 return Number::one();
978 if (n == 1)
979 return f;
980 auto r = power(f, n / 2);
981 r *= r;
982 if (n % 2 != 0)
983 r *= f;
984 return r;
985}
986
987// Returns f^(1/d)
988// Uses Newton–Raphson iterations until the result stops changing
989// to find the non-negative root of the polynomial g(x) = x^d - f
990
991// This function, and power(Number f, unsigned n, unsigned d)
992// treat corner cases such as 0 roots as advised by Annex F of
993// the C standard, which itself is consistent with the IEEE
994// floating point standards.
995
996Number
997root(Number f, unsigned d)
998{
999 constexpr Number zero = Number{};
1000 auto const one = Number::one();
1001
1002 if (f == one || d == 1)
1003 return f;
1004 if (d == 0)
1005 {
1006 if (f == -one)
1007 return one;
1008 if (abs(f) < one)
1009 return zero;
1010 throw std::overflow_error("Number::root infinity");
1011 }
1012 if (f < zero && d % 2 == 0)
1013 throw std::overflow_error("Number::root nan");
1014 if (f == zero)
1015 return f;
1016
1017 // Scale f into the range (0, 1) such that f's exponent is a multiple of d
1018 auto e = f.exponent_ + Number::mantissaLog() + 1;
1019 auto const di = static_cast<int>(d);
1020 auto ex = [e = e, di = di]() // Euclidean remainder of e/d
1021 {
1022 int k = (e >= 0 ? e : e - (di - 1)) / di;
1023 int k2 = e - k * di;
1024 if (k2 == 0)
1025 return 0;
1026 return di - k2;
1027 }();
1028 e += ex;
1029 f = f.shiftExponent(-e); // f /= 10^e;
1030
1031 XRPL_ASSERT_PARTS(
1032 f.isnormal(), "xrpl::root(Number, unsigned)", "f is normalized");
1033 bool neg = false;
1034 if (f < zero)
1035 {
1036 neg = true;
1037 f = -f;
1038 }
1039
1040 // Quadratic least squares curve fit of f^(1/d) in the range [0, 1]
1041 auto const D = ((6 * di + 11) * di + 6) * di + 1;
1042 auto const a0 = 3 * di * ((2 * di - 3) * di + 1);
1043 auto const a1 = 24 * di * (2 * di - 1);
1044 auto const a2 = -30 * (di - 1) * di;
1045 Number r = ((Number{a2} * f + Number{a1}) * f + Number{a0}) / Number{D};
1046 if (neg)
1047 {
1048 f = -f;
1049 r = -r;
1050 }
1051
1052 // Newton–Raphson iteration of f^(1/d) with initial guess r
1053 // halt when r stops changing, checking for bouncing on the last iteration
1054 Number rm1{};
1055 Number rm2{};
1056 do
1057 {
1058 rm2 = rm1;
1059 rm1 = r;
1060 r = (Number(d - 1) * r + f / power(r, d - 1)) / Number(d);
1061 } while (r != rm1 && r != rm2);
1062
1063 // return r * 10^(e/d) to reverse scaling
1064 auto const result = r.shiftExponent(e / di);
1065 XRPL_ASSERT_PARTS(
1066 result.isnormal(),
1067 "xrpl::root(Number, unsigned)",
1068 "result is normalized");
1069 return result;
1070}
1071
1072Number
1074{
1075 constexpr Number zero = Number{};
1076 auto const one = Number::one();
1077
1078 if (f == one)
1079 return f;
1080 if (f < zero)
1081 throw std::overflow_error("Number::root nan");
1082 if (f == zero)
1083 return f;
1084
1085 // Scale f into the range (0, 1) such that f's exponent is a multiple of d
1086 auto e = f.exponent_ + Number::mantissaLog() + 1;
1087 if (e % 2 != 0)
1088 ++e;
1089 f = f.shiftExponent(-e); // f /= 10^e;
1090 XRPL_ASSERT_PARTS(f.isnormal(), "xrpl::root2(Number)", "f is normalized");
1091
1092 // Quadratic least squares curve fit of f^(1/d) in the range [0, 1]
1093 auto const D = 105;
1094 auto const a0 = 18;
1095 auto const a1 = 144;
1096 auto const a2 = -60;
1097 Number r = ((Number{a2} * f + Number{a1}) * f + Number{a0}) / Number{D};
1098
1099 // Newton–Raphson iteration of f^(1/2) with initial guess r
1100 // halt when r stops changing, checking for bouncing on the last iteration
1101 Number rm1{};
1102 Number rm2{};
1103 do
1104 {
1105 rm2 = rm1;
1106 rm1 = r;
1107 r = (r + f / r) / Number(2);
1108 } while (r != rm1 && r != rm2);
1109
1110 // return r * 10^(e/2) to reverse scaling
1111 auto const result = r.shiftExponent(e / 2);
1112 XRPL_ASSERT_PARTS(
1113 result.isnormal(), "xrpl::root2(Number)", "result is normalized");
1114
1115 return result;
1116}
1117
1118// Returns f^(n/d)
1119
1120Number
1121power(Number const& f, unsigned n, unsigned d)
1122{
1123 constexpr Number zero = Number{};
1124 auto const one = Number::one();
1125
1126 if (f == one)
1127 return f;
1128 auto g = std::gcd(n, d);
1129 if (g == 0)
1130 throw std::overflow_error("Number::power nan");
1131 if (d == 0)
1132 {
1133 if (f == -one)
1134 return one;
1135 if (abs(f) < one)
1136 return zero;
1137 // abs(f) > one
1138 throw std::overflow_error("Number::power infinity");
1139 }
1140 if (n == 0)
1141 return one;
1142 n /= g;
1143 d /= g;
1144 if ((n % 2) == 1 && (d % 2) == 0 && f < zero)
1145 throw std::overflow_error("Number::power nan");
1146 return root(power(f, n), d);
1147}
1148
1149} // namespace xrpl
T append(T... args)
T begin(T... args)
int round() noexcept
Definition Number.cpp:186
void set_positive() noexcept
Definition Number.cpp:141
unsigned pop() noexcept
Definition Number.cpp:174
void doRoundUp(bool &negative, T &mantissa, int &exponent, internalrep const &minMantissa, internalrep const &maxMantissa, std::string location)
Definition Number.cpp:249
void bringIntoRange(bool &negative, T &mantissa, int &exponent, internalrep const &minMantissa)
Definition Number.cpp:224
void doRound(rep &drops, std::string location)
Definition Number.cpp:297
bool is_negative() const noexcept
Definition Number.cpp:153
void doRoundDown(bool &negative, T &mantissa, int &exponent, internalrep const &minMantissa)
Definition Number.cpp:276
void doPush(unsigned d) noexcept
Definition Number.cpp:159
void set_negative() noexcept
Definition Number.cpp:147
std::uint8_t xbit_
Definition Number.cpp:72
std::uint8_t sbit_
Definition Number.cpp:73
void push(T d) noexcept
Definition Number.cpp:168
std::uint64_t digits_
Definition Number.cpp:71
Number is a floating point type that can represent a wide range of values.
Definition Number.h:211
static constexpr Number oneSmall()
oneSmall is needed because the ranges are private
Definition Number.cpp:345
static rounding_mode getround()
Definition Number.cpp:34
internalrep mantissa_
Definition Number.h:216
static internalrep minMantissa()
Definition Number.h:417
constexpr rep mantissa() const noexcept
Returns the mantissa of the external view of the Number.
Definition Number.h:570
static rounding_mode setround(rounding_mode mode)
Definition Number.cpp:40
Number & operator/=(Number const &x)
Definition Number.cpp:730
Number & operator+=(Number const &x)
Definition Number.cpp:537
Number truncate() const noexcept
Definition Number.cpp:856
std::int64_t rep
Definition Number.h:212
friend std::string to_string(Number const &amount)
Definition Number.cpp:874
static constexpr MantissaRange smallRange
Definition Number.h:455
friend void doNormalize(bool &negative, T &mantissa_, int &exponent_, MantissaRange::rep const &minMantissa, MantissaRange::rep const &maxMantissa)
Definition Number.cpp:381
static constexpr internalrep maxRep
Definition Number.h:224
MantissaRange::rep internalrep
Definition Number.h:213
static thread_local rounding_mode mode_
Definition Number.h:452
static constexpr int minExponent
Definition Number.h:221
Number shiftExponent(int exponentDelta) const
Definition Number.cpp:518
static void setMantissaScale(MantissaRange::mantissa_scale scale)
Changes which mantissa scale is used for normalization.
Definition Number.cpp:52
static internalrep externalToInternal(rep mantissa)
Definition Number.cpp:326
static internalrep maxMantissa()
Definition Number.h:423
bool isnormal() const noexcept
Definition Number.h:710
constexpr int exponent() const noexcept
Returns the exponent of the external view of the Number.
Definition Number.h:591
static constexpr int maxExponent
Definition Number.h:222
static thread_local std::reference_wrapper< MantissaRange const > range_
Definition Number.h:473
friend Number root2(Number f)
Definition Number.cpp:1073
static MantissaRange::mantissa_scale getMantissaScale()
Returns which mantissa scale is currently in use for normalization.
Definition Number.cpp:46
int exponent_
Definition Number.h:217
static constexpr MantissaRange largeRange
Definition Number.h:462
void normalize()
Definition Number.cpp:508
static Number one()
Definition Number.cpp:369
Number & operator*=(Number const &x)
Definition Number.cpp:667
constexpr Number()=default
static constexpr Number oneLarge()
oneLarge is needed because the ranges are private
Definition Number.cpp:357
bool negative_
Definition Number.h:215
static int mantissaLog()
Definition Number.h:429
friend Number root(Number f, unsigned d)
Definition Number.cpp:997
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 make_reverse_iterator(T... args)
STL namespace.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
ClosedInterval< T > range(T low, T high)
Create a closed range interval.
Definition RangeSet.h:35
Number power(Number const &f, unsigned n)
Definition Number.cpp:974
constexpr Number oneSml
Definition Number.cpp:354
constexpr Number abs(Number x) noexcept
Definition Number.h:740
static unsigned divu10(uint128_t &u)
Definition Number.cpp:645
constexpr Number oneLrg
Definition Number.cpp:366
T reserve(T... args)
T length(T... args)
T to_string(T... args)