rippled
Loading...
Searching...
No Matches
Number.cpp
1#include <xrpl/basics/Number.h>
2#include <xrpl/beast/utility/instrumentation.h>
3
4#include <algorithm>
5#include <cstddef>
6#include <cstdint>
7#include <iterator>
8#include <limits>
9#include <numeric>
10#include <stdexcept>
11#include <string>
12#include <type_traits>
13#include <utility>
14
15#ifdef _MSC_VER
16#pragma message("Using boost::multiprecision::uint128_t")
17#include <boost/multiprecision/cpp_int.hpp>
18using uint128_t = boost::multiprecision::uint128_t;
19#else // !defined(_MSC_VER)
20using uint128_t = __uint128_t;
21#endif // !defined(_MSC_VER)
22
23namespace ripple {
24
26
29{
30 return mode_;
31}
32
35{
36 return std::exchange(mode_, mode);
37}
38
39// Guard
40
41// The Guard class is used to tempoarily add extra digits of
42// preicision to an operation. This enables the final result
43// to be correctly rounded to the internal precision of Number.
44
46{
47 std::uint64_t digits_; // 16 decimal guard digits
48 std::uint8_t xbit_ : 1; // has a non-zero digit been shifted off the end
49 std::uint8_t sbit_ : 1; // the sign of the guard digits
50
51public:
52 explicit Guard() : digits_{0}, xbit_{0}, sbit_{0}
53 {
54 }
55
56 // set & test the sign bit
57 void
58 set_positive() noexcept;
59 void
60 set_negative() noexcept;
61 bool
62 is_negative() const noexcept;
63
64 // add a digit
65 void
66 push(unsigned d) noexcept;
67
68 // recover a digit
69 unsigned
70 pop() noexcept;
71
72 // Indicate round direction: 1 is up, -1 is down, 0 is even
73 // This enables the client to round towards nearest, and on
74 // tie, round towards even.
75 int
76 round() noexcept;
77
78 // Modify the result to the correctly rounded value
79 void
80 doRoundUp(rep& mantissa, int& exponent, std::string location);
81
82 // Modify the result to the correctly rounded value
83 void
85
86 // Modify the result to the correctly rounded value
87 void
88 doRound(rep& drops);
89};
90
91inline void
93{
94 sbit_ = 0;
95}
96
97inline void
99{
100 sbit_ = 1;
101}
102
103inline bool
105{
106 return sbit_ == 1;
107}
108
109inline void
110Number::Guard::push(unsigned d) noexcept
111{
112 xbit_ = xbit_ || (digits_ & 0x0000'0000'0000'000F) != 0;
113 digits_ >>= 4;
114 digits_ |= (d & 0x0000'0000'0000'000FULL) << 60;
115}
116
117inline unsigned
119{
120 unsigned d = (digits_ & 0xF000'0000'0000'0000) >> 60;
121 digits_ <<= 4;
122 return d;
123}
124
125// Returns:
126// -1 if Guard is less than half
127// 0 if Guard is exactly half
128// 1 if Guard is greater than half
129int
131{
132 auto mode = Number::getround();
133
134 if (mode == towards_zero)
135 return -1;
136
137 if (mode == downward)
138 {
139 if (sbit_)
140 {
141 if (digits_ > 0 || xbit_)
142 return 1;
143 }
144 return -1;
145 }
146
147 if (mode == upward)
148 {
149 if (sbit_)
150 return -1;
151 if (digits_ > 0 || xbit_)
152 return 1;
153 return -1;
154 }
155
156 // assume round to nearest if mode is not one of the predefined values
157 if (digits_ > 0x5000'0000'0000'0000)
158 return 1;
159 if (digits_ < 0x5000'0000'0000'0000)
160 return -1;
161 if (xbit_)
162 return 1;
163 return 0;
164}
165
166void
168{
169 auto r = round();
170 if (r == 1 || (r == 0 && (mantissa & 1) == 1))
171 {
172 ++mantissa;
173 if (mantissa > maxMantissa)
174 {
175 mantissa /= 10;
176 ++exponent;
177 }
178 }
179 if (exponent < minExponent)
180 {
181 mantissa = 0;
183 }
184 if (exponent > maxExponent)
185 throw std::overflow_error(location);
186}
187
188void
190{
191 auto r = round();
192 if (r == 1 || (r == 0 && (mantissa & 1) == 1))
193 {
194 --mantissa;
195 if (mantissa < minMantissa)
196 {
197 mantissa *= 10;
198 --exponent;
199 }
200 }
201 if (exponent < minExponent)
202 {
203 mantissa = 0;
205 }
206}
207
208// Modify the result to the correctly rounded value
209void
211{
212 auto r = round();
213 if (r == 1 || (r == 0 && (drops & 1) == 1))
214 {
215 ++drops;
216 }
217 if (is_negative())
218 drops = -drops;
219}
220
221// Number
222
223constexpr Number one{1000000000000000, -15, Number::unchecked{}};
224
225void
227{
228 if (mantissa_ == 0)
229 {
230 *this = Number{};
231 return;
232 }
233 bool const negative = (mantissa_ < 0);
234 auto m = static_cast<std::make_unsigned_t<rep>>(mantissa_);
235 if (negative)
236 m = -m;
237 while ((m < minMantissa) && (exponent_ > minExponent))
238 {
239 m *= 10;
240 --exponent_;
241 }
242 Guard g;
243 if (negative)
244 g.set_negative();
245 while (m > maxMantissa)
246 {
247 if (exponent_ >= maxExponent)
248 throw std::overflow_error("Number::normalize 1");
249 g.push(m % 10);
250 m /= 10;
251 ++exponent_;
252 }
253 mantissa_ = m;
255 {
256 *this = Number{};
257 return;
258 }
259
260 g.doRoundUp(mantissa_, exponent_, "Number::normalize 2");
261
262 if (negative)
264}
265
266Number&
268{
269 if (y == Number{})
270 return *this;
271 if (*this == Number{})
272 {
273 *this = y;
274 return *this;
275 }
276 if (*this == -y)
277 {
278 *this = Number{};
279 return *this;
280 }
281 XRPL_ASSERT(
282 isnormal() && y.isnormal(),
283 "ripple::Number::operator+=(Number) : is normal");
284 auto xm = mantissa();
285 auto xe = exponent();
286 int xn = 1;
287 if (xm < 0)
288 {
289 xm = -xm;
290 xn = -1;
291 }
292 auto ym = y.mantissa();
293 auto ye = y.exponent();
294 int yn = 1;
295 if (ym < 0)
296 {
297 ym = -ym;
298 yn = -1;
299 }
300 Guard g;
301 if (xe < ye)
302 {
303 if (xn == -1)
304 g.set_negative();
305 do
306 {
307 g.push(xm % 10);
308 xm /= 10;
309 ++xe;
310 } while (xe < ye);
311 }
312 else if (xe > ye)
313 {
314 if (yn == -1)
315 g.set_negative();
316 do
317 {
318 g.push(ym % 10);
319 ym /= 10;
320 ++ye;
321 } while (xe > ye);
322 }
323 if (xn == yn)
324 {
325 xm += ym;
326 if (xm > maxMantissa)
327 {
328 g.push(xm % 10);
329 xm /= 10;
330 ++xe;
331 }
332 g.doRoundUp(xm, xe, "Number::addition overflow");
333 }
334 else
335 {
336 if (xm > ym)
337 {
338 xm = xm - ym;
339 }
340 else
341 {
342 xm = ym - xm;
343 xe = ye;
344 xn = yn;
345 }
346 while (xm < minMantissa)
347 {
348 xm *= 10;
349 xm -= g.pop();
350 --xe;
351 }
352 g.doRoundDown(xm, xe);
353 }
354 mantissa_ = xm * xn;
355 exponent_ = xe;
356 return *this;
357}
358
359// Optimization equivalent to:
360// auto r = static_cast<unsigned>(u % 10);
361// u /= 10;
362// return r;
363// Derived from Hacker's Delight Second Edition Chapter 10
364// by Henry S. Warren, Jr.
365static inline unsigned
366divu10(uint128_t& u)
367{
368 // q = u * 0.75
369 auto q = (u >> 1) + (u >> 2);
370 // iterate towards q = u * 0.8
371 q += q >> 4;
372 q += q >> 8;
373 q += q >> 16;
374 q += q >> 32;
375 q += q >> 64;
376 // q /= 8 approximately == u / 10
377 q >>= 3;
378 // r = u - q * 10 approximately == u % 10
379 auto r = static_cast<unsigned>(u - ((q << 3) + (q << 1)));
380 // correction c is 1 if r >= 10 else 0
381 auto c = (r + 6) >> 4;
382 u = q + c;
383 r -= c * 10;
384 return r;
385}
386
387Number&
389{
390 if (*this == Number{})
391 return *this;
392 if (y == Number{})
393 {
394 *this = y;
395 return *this;
396 }
397 XRPL_ASSERT(
398 isnormal() && y.isnormal(),
399 "ripple::Number::operator*=(Number) : is normal");
400 auto xm = mantissa();
401 auto xe = exponent();
402 int xn = 1;
403 if (xm < 0)
404 {
405 xm = -xm;
406 xn = -1;
407 }
408 auto ym = y.mantissa();
409 auto ye = y.exponent();
410 int yn = 1;
411 if (ym < 0)
412 {
413 ym = -ym;
414 yn = -1;
415 }
416 auto zm = uint128_t(xm) * uint128_t(ym);
417 auto ze = xe + ye;
418 auto zn = xn * yn;
419 Guard g;
420 if (zn == -1)
421 g.set_negative();
422 while (zm > maxMantissa)
423 {
424 // The following is optimization for:
425 // g.push(static_cast<unsigned>(zm % 10));
426 // zm /= 10;
427 g.push(divu10(zm));
428 ++ze;
429 }
430 xm = static_cast<rep>(zm);
431 xe = ze;
432 g.doRoundUp(
433 xm,
434 xe,
435 "Number::multiplication overflow : exponent is " + std::to_string(xe));
436 mantissa_ = xm * zn;
437 exponent_ = xe;
438 XRPL_ASSERT(
439 isnormal() || *this == Number{},
440 "ripple::Number::operator*=(Number) : result is normal");
441 return *this;
442}
443
444Number&
446{
447 if (y == Number{})
448 throw std::overflow_error("Number: divide by 0");
449 if (*this == Number{})
450 return *this;
451 int np = 1;
452 auto nm = mantissa();
453 auto ne = exponent();
454 if (nm < 0)
455 {
456 nm = -nm;
457 np = -1;
458 }
459 int dp = 1;
460 auto dm = y.mantissa();
461 auto de = y.exponent();
462 if (dm < 0)
463 {
464 dm = -dm;
465 dp = -1;
466 }
467 // Shift by 10^17 gives greatest precision while not overflowing uint128_t
468 // or the cast back to int64_t
469 uint128_t const f = 100'000'000'000'000'000;
470 mantissa_ = static_cast<std::int64_t>(uint128_t(nm) * f / uint128_t(dm));
471 exponent_ = ne - de - 17;
472 mantissa_ *= np * dp;
473 normalize();
474 return *this;
475}
476
477Number::operator rep() const
478{
479 rep drops = mantissa_;
480 int offset = exponent_;
481 Guard g;
482 if (drops != 0)
483 {
484 if (drops < 0)
485 {
486 g.set_negative();
487 drops = -drops;
488 }
489 for (; offset < 0; ++offset)
490 {
491 g.push(drops % 10);
492 drops /= 10;
493 }
494 for (; offset > 0; --offset)
495 {
496 if (drops > std::numeric_limits<decltype(drops)>::max() / 10)
497 throw std::overflow_error("Number::operator rep() overflow");
498 drops *= 10;
499 }
500 g.doRound(drops);
501 }
502 return drops;
503}
504
505Number
506Number::truncate() const noexcept
507{
508 if (exponent_ >= 0 || mantissa_ == 0)
509 return *this;
510
511 Number ret = *this;
512 while (ret.exponent_ < 0 && ret.mantissa_ != 0)
513 {
514 ret.exponent_ += 1;
515 ret.mantissa_ /= rep(10);
516 }
517 // We are guaranteed that normalize() will never throw an exception
518 // because exponent is either negative or zero at this point.
519 ret.normalize();
520 return ret;
521}
522
524to_string(Number const& amount)
525{
526 // keep full internal accuracy, but make more human friendly if possible
527 if (amount == Number{})
528 return "0";
529
530 auto const exponent = amount.exponent();
531 auto mantissa = amount.mantissa();
532
533 // Use scientific notation for exponents that are too small or too large
534 if (((exponent != 0) && ((exponent < -25) || (exponent > -5))))
535 {
537 ret.append(1, 'e');
539 return ret;
540 }
541
542 bool negative = false;
543
544 if (mantissa < 0)
545 {
547 negative = true;
548 }
549
550 XRPL_ASSERT(
551 exponent + 43 > 0, "ripple::to_string(Number) : minimum exponent");
552
553 ptrdiff_t const pad_prefix = 27;
554 ptrdiff_t const pad_suffix = 23;
555
556 std::string const raw_value(std::to_string(mantissa));
557 std::string val;
558
559 val.reserve(raw_value.length() + pad_prefix + pad_suffix);
560 val.append(pad_prefix, '0');
561 val.append(raw_value);
562 val.append(pad_suffix, '0');
563
564 ptrdiff_t const offset(exponent + 43);
565
566 auto pre_from(val.begin());
567 auto const pre_to(val.begin() + offset);
568
569 auto const post_from(val.begin() + offset);
570 auto post_to(val.end());
571
572 // Crop leading zeroes. Take advantage of the fact that there's always a
573 // fixed amount of leading zeroes and skip them.
574 if (std::distance(pre_from, pre_to) > pad_prefix)
575 pre_from += pad_prefix;
576
577 XRPL_ASSERT(
578 post_to >= post_from,
579 "ripple::to_string(Number) : first distance check");
580
581 pre_from = std::find_if(pre_from, pre_to, [](char c) { return c != '0'; });
582
583 // Crop trailing zeroes. Take advantage of the fact that there's always a
584 // fixed amount of trailing zeroes and skip them.
585 if (std::distance(post_from, post_to) > pad_suffix)
586 post_to -= pad_suffix;
587
588 XRPL_ASSERT(
589 post_to >= post_from,
590 "ripple::to_string(Number) : second distance check");
591
592 post_to = std::find_if(
595 [](char c) { return c != '0'; })
596 .base();
597
598 std::string ret;
599
600 if (negative)
601 ret.append(1, '-');
602
603 // Assemble the output:
604 if (pre_from == pre_to)
605 ret.append(1, '0');
606 else
607 ret.append(pre_from, pre_to);
608
609 if (post_to != post_from)
610 {
611 ret.append(1, '.');
612 ret.append(post_from, post_to);
613 }
614
615 return ret;
616}
617
618// Returns f^n
619// Uses a log_2(n) number of multiplications
620
621Number
622power(Number const& f, unsigned n)
623{
624 if (n == 0)
625 return one;
626 if (n == 1)
627 return f;
628 auto r = power(f, n / 2);
629 r *= r;
630 if (n % 2 != 0)
631 r *= f;
632 return r;
633}
634
635// Returns f^(1/d)
636// Uses Newton–Raphson iterations until the result stops changing
637// to find the non-negative root of the polynomial g(x) = x^d - f
638
639// This function, and power(Number f, unsigned n, unsigned d)
640// treat corner cases such as 0 roots as advised by Annex F of
641// the C standard, which itself is consistent with the IEEE
642// floating point standards.
643
644Number
645root(Number f, unsigned d)
646{
647 if (f == one || d == 1)
648 return f;
649 if (d == 0)
650 {
651 if (f == -one)
652 return one;
653 if (abs(f) < one)
654 return Number{};
655 throw std::overflow_error("Number::root infinity");
656 }
657 if (f < Number{} && d % 2 == 0)
658 throw std::overflow_error("Number::root nan");
659 if (f == Number{})
660 return f;
661
662 // Scale f into the range (0, 1) such that f's exponent is a multiple of d
663 auto e = f.exponent() + 16;
664 auto const di = static_cast<int>(d);
665 auto ex = [e = e, di = di]() // Euclidean remainder of e/d
666 {
667 int k = (e >= 0 ? e : e - (di - 1)) / di;
668 int k2 = e - k * di;
669 if (k2 == 0)
670 return 0;
671 return di - k2;
672 }();
673 e += ex;
674 f = Number{f.mantissa(), f.exponent() - e}; // f /= 10^e;
675 bool neg = false;
676 if (f < Number{})
677 {
678 neg = true;
679 f = -f;
680 }
681
682 // Quadratic least squares curve fit of f^(1/d) in the range [0, 1]
683 auto const D = ((6 * di + 11) * di + 6) * di + 1;
684 auto const a0 = 3 * di * ((2 * di - 3) * di + 1);
685 auto const a1 = 24 * di * (2 * di - 1);
686 auto const a2 = -30 * (di - 1) * di;
687 Number r = ((Number{a2} * f + Number{a1}) * f + Number{a0}) / Number{D};
688 if (neg)
689 {
690 f = -f;
691 r = -r;
692 }
693
694 // Newton–Raphson iteration of f^(1/d) with initial guess r
695 // halt when r stops changing, checking for bouncing on the last iteration
696 Number rm1{};
697 Number rm2{};
698 do
699 {
700 rm2 = rm1;
701 rm1 = r;
702 r = (Number(d - 1) * r + f / power(r, d - 1)) / Number(d);
703 } while (r != rm1 && r != rm2);
704
705 // return r * 10^(e/d) to reverse scaling
706 return Number{r.mantissa(), r.exponent() + e / di};
707}
708
709Number
711{
712 if (f == one)
713 return f;
714 if (f < Number{})
715 throw std::overflow_error("Number::root nan");
716 if (f == Number{})
717 return f;
718
719 // Scale f into the range (0, 1) such that f's exponent is a multiple of d
720 auto e = f.exponent() + 16;
721 if (e % 2 != 0)
722 ++e;
723 f = Number{f.mantissa(), f.exponent() - e}; // f /= 10^e;
724
725 // Quadratic least squares curve fit of f^(1/d) in the range [0, 1]
726 auto const D = 105;
727 auto const a0 = 18;
728 auto const a1 = 144;
729 auto const a2 = -60;
730 Number r = ((Number{a2} * f + Number{a1}) * f + Number{a0}) / Number{D};
731
732 // Newton–Raphson iteration of f^(1/2) with initial guess r
733 // halt when r stops changing, checking for bouncing on the last iteration
734 Number rm1{};
735 Number rm2{};
736 do
737 {
738 rm2 = rm1;
739 rm1 = r;
740 r = (r + f / r) / Number(2);
741 } while (r != rm1 && r != rm2);
742
743 // return r * 10^(e/2) to reverse scaling
744 return Number{r.mantissa(), r.exponent() + e / 2};
745}
746
747// Returns f^(n/d)
748
749Number
750power(Number const& f, unsigned n, unsigned d)
751{
752 if (f == one)
753 return f;
754 auto g = std::gcd(n, d);
755 if (g == 0)
756 throw std::overflow_error("Number::power nan");
757 if (d == 0)
758 {
759 if (f == -one)
760 return one;
761 if (abs(f) < one)
762 return Number{};
763 // abs(f) > one
764 throw std::overflow_error("Number::power infinity");
765 }
766 if (n == 0)
767 return one;
768 n /= g;
769 d /= g;
770 if ((n % 2) == 1 && (d % 2) == 0 && f < Number{})
771 throw std::overflow_error("Number::power nan");
772 return root(power(f, n), d);
773}
774
775} // namespace ripple
T append(T... args)
T begin(T... args)
void set_negative() noexcept
Definition Number.cpp:98
void doRoundDown(rep &mantissa, int &exponent)
Definition Number.cpp:189
void doRoundUp(rep &mantissa, int &exponent, std::string location)
Definition Number.cpp:167
void push(unsigned d) noexcept
Definition Number.cpp:110
unsigned pop() noexcept
Definition Number.cpp:118
bool is_negative() const noexcept
Definition Number.cpp:104
std::uint8_t xbit_
Definition Number.cpp:48
std::uint64_t digits_
Definition Number.cpp:47
int round() noexcept
Definition Number.cpp:130
std::uint8_t sbit_
Definition Number.cpp:49
void set_positive() noexcept
Definition Number.cpp:92
void doRound(rep &drops)
Definition Number.cpp:210
constexpr bool isnormal() const noexcept
Definition Number.h:321
Number & operator+=(Number const &x)
Definition Number.cpp:267
static constexpr std::int64_t maxMantissa
Definition Number.h:35
static constexpr int maxExponent
Definition Number.h:40
Number & operator/=(Number const &x)
Definition Number.cpp:445
Number truncate() const noexcept
Definition Number.cpp:506
static constexpr std::int64_t minMantissa
Definition Number.h:33
constexpr int exponent() const noexcept
Definition Number.h:215
static thread_local rounding_mode mode_
Definition Number.h:181
void normalize()
Definition Number.cpp:226
static constexpr Number max() noexcept
Definition Number.h:309
int exponent_
Definition Number.h:29
static rounding_mode getround()
Definition Number.cpp:28
Number & operator*=(Number const &x)
Definition Number.cpp:388
static constexpr int minExponent
Definition Number.h:39
std::int64_t rep
Definition Number.h:27
static rounding_mode setround(rounding_mode mode)
Definition Number.cpp:34
constexpr rep mantissa() const noexcept
Definition Number.h:209
constexpr Number()=default
rep mantissa_
Definition Number.h:28
T distance(T... args)
T end(T... args)
T exchange(T... args)
T find_if(T... args)
T gcd(T... args)
T make_reverse_iterator(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
constexpr Number one
Definition Number.cpp:223
static unsigned divu10(uint128_t &u)
Definition Number.cpp:366
Number power(Number const &f, unsigned n)
Definition Number.cpp:622
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:611
Number root(Number f, unsigned d)
Definition Number.cpp:645
Number root2(Number f)
Definition Number.cpp:710
constexpr Number abs(Number x) noexcept
Definition Number.h:329
STL namespace.
T reserve(T... args)
T length(T... args)
T to_string(T... args)