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