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