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