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