xrpld
Loading...
Searching...
No Matches
tests/libxrpl/basics/Number.cpp
1#include <xrpl/basics/Number.h>
2
3#include <xrpl/beast/utility/Zero.h>
4#include <xrpl/protocol/IOUAmount.h>
5#include <xrpl/protocol/Issue.h>
6#include <xrpl/protocol/STAmount.h>
7#include <xrpl/protocol/SystemParameters.h>
8#include <xrpl/protocol/XRPAmount.h>
9
10// NOLINTNEXTLINE(misc-include-cleaner)
11#include <boost/multiprecision/cpp_dec_float.hpp>
12#include <boost/multiprecision/number.hpp>
13
14#include <gtest/gtest.h>
15
16#include <algorithm>
17#include <array>
18#include <cctype>
19#include <cstdint>
20#include <functional>
21#include <iomanip>
22#include <limits>
23#include <map>
24#include <ranges>
25#include <sstream>
26#include <stdexcept>
27#include <string>
28#include <tuple>
29#include <utility>
30#include <vector>
31
32namespace xrpl {
33
34using BigInt = boost::multiprecision::cpp_int;
35using Dec = boost::multiprecision::cpp_dec_float_50;
36
37static std::string
38fmt(BigInt const& value)
39{
40 auto s = to_string(value);
41 std::string out;
42 int count = 0;
43 for (char const& ch : std::views::reverse(s))
44 {
45 if (count != 0 && count % 3 == 0 && (isdigit(ch) != 0))
46 out.insert(out.begin(), '_');
47 out.insert(out.begin(), ch);
48 ++count;
49 }
50 return out;
51}
52
55{
56 BigInt v = n.mantissa();
57 auto e = n.exponent();
58
59 for (; e > 0; --e)
60 v *= 10;
61 for (; e < 0; ++e)
62 {
63 EXPECT_EQ(v % 10, 0);
64 v /= 10;
65 }
66 return v;
67}
68
69template <class T = Dec>
70static T
71pow10(int n)
72{
73 if (n == 0)
74 return 1;
75 if (n == 1)
76 return 10;
77
78 if (n > 1)
79 {
80 auto r = pow10<T>(n / 2);
81 r *= r;
82 if (n % 2 != 0)
83 r *= 10;
84 return r;
85 }
86
87 T p = 1;
88 p /= pow10<T>(-n);
89 return p;
90}
91
92static std::string
93fmt(Dec const& value)
94{
96 os << std::setprecision(40) << value;
97 return os.str();
98}
99
100TEST(NumberTest, zero)
101{
102 for (auto const mantissaScale : MantissaRange::getAllScales())
103 {
104 NumberMantissaScaleGuard const sg(mantissaScale);
105
106 for (Number const& z : {Number{0, 0}, Number{0}})
107 {
108 EXPECT_EQ(z.mantissa(), 0);
109 EXPECT_EQ(z.exponent(), Number{}.exponent());
110
111 EXPECT_EQ((z + z), z);
112 EXPECT_EQ((z - z), z);
113 EXPECT_EQ(z, -z);
114 }
115 }
116}
117
118TEST(NumberTest, limits)
119{
120 for (auto const mantissaScale : MantissaRange::getAllScales())
121 {
122 NumberMantissaScaleGuard const sg(mantissaScale);
123
124 auto const scale = Number::getMantissaScale();
125 bool caught = false;
126 auto const minMantissa = Number::minMantissa();
127 try
128 {
129 [[maybe_unused]] Number const x =
130 Number{false, minMantissa * 10, 32768, Number::Normalized{}};
131 }
132 catch (std::overflow_error const&)
133 {
134 caught = true;
135 }
136 EXPECT_TRUE(caught);
137
138 auto test = [](auto const& x, auto const& y, int line) {
139 auto const result = x == y;
141 ss << x << " == " << y << " -> " << (result ? "true" : "false");
142 EXPECT_TRUE(result) << ss.str() << " (" << __FILE__ << ":" << line << ")";
143 };
144
145 test(
146 Number{false, minMantissa * 10, 32767, Number::Normalized{}},
147 Number{false, minMantissa, 32768, Number::Normalized{}},
148 __LINE__);
149 test(Number{false, minMantissa, -32769, Number::Normalized{}}, Number{}, __LINE__);
150 test(
151 Number{false, minMantissa, 32000, Number::Normalized{}} * 1'000 +
152 Number{false, 1'500, 32000, Number::Normalized{}},
153 Number{false, minMantissa + 2, 32003, Number::Normalized{}},
154 __LINE__);
155 // 9,223,372,036,854,775,808
156
157 test(
160 ? Number{-9'223'372'036'854'776, 3}
161 : Number{true, 9'223'372'036'854'775'808ULL, 0, Number::Normalized{}},
162 __LINE__);
163 test(
165 scale == MantissaRange::MantissaScale::Small ? Number{-9'223'372'036'854'776, 3}
166 : Number{-9'223'372'036'854'775'807},
167 __LINE__);
168 test(
170 Number{
172 ? 9'223'372'036'854'776
174 18 - Number::mantissaLog()},
175 __LINE__);
176 caught = false;
177 try
178 {
179 [[maybe_unused]]
180 Number const q = Number{false, minMantissa, 32767, Number::Normalized{}} * 100;
181 }
182 catch (std::overflow_error const&)
183 {
184 caught = true;
185 }
186 EXPECT_TRUE(caught);
187
188 try
189 {
190 Number{1, 2000000, Number::Normalized{}};
191 ADD_FAILURE();
192 }
193 catch (std::overflow_error const& e)
194 {
195 std::string const expected = "Number::normalize 2";
196 EXPECT_EQ(e.what(), expected) << e.what();
197 }
198
200 {
201 // Normalization with the other scales, including the older large mantissa scales, will
202 // overflow.
204 // The display of large exponents won't go above kMaxExponent
205 EXPECT_EQ(to_string(bigNum), "9223372036854775810e32768") << bigNum;
206 // Perhaps surprisingly, this is ok, because the exponent range is related to when the
207 // number is _normalized_, and for mantissas > kMaxRep, the accessors return values that
208 // are not normalized.
209 EXPECT_EQ(bigNum.mantissa(), 922337203685477581ULL) << bigNum.mantissa();
210 EXPECT_EQ(bigNum.exponent(), 32769) << bigNum.exponent();
211 }
212 else
213 {
214 try
215 {
217 ADD_FAILURE();
218 }
219 catch (std::overflow_error const& e)
220 {
221 std::string const expected =
222 (scale == MantissaRange::MantissaScale::Small ? "Number::normalize 1"
223 : "Number::normalize 1.5");
224 EXPECT_EQ(e.what(), expected) << e.what();
225 }
226 }
227 }
228}
229
230TEST(NumberTest, add)
231{
232 for (auto const mantissaScale : MantissaRange::getAllScales())
233 {
234 NumberMantissaScaleGuard const sg(mantissaScale);
235
236 auto const scale = Number::getMantissaScale();
237
240
242 // TODO: Move these to the blocks where they're used
243 auto const cSmall = std::to_array<Case>({
244 {Number{1'000'000'000'000'000, -15},
245 Number{6'555'555'555'555'555, -29},
246 Number{1'000'000'000'000'066, -15},
247 __LINE__},
248 {Number{-1'000'000'000'000'000, -15},
249 Number{-6'555'555'555'555'555, -29},
250 Number{-1'000'000'000'000'066, -15},
251 __LINE__},
252 {Number{-1'000'000'000'000'000, -15},
253 Number{6'555'555'555'555'555, -29},
254 Number{-9'999'999'999'999'344, -16},
255 __LINE__},
256 {Number{-6'555'555'555'555'555, -29},
257 Number{1'000'000'000'000'000, -15},
258 Number{9'999'999'999'999'344, -16},
259 __LINE__},
260 {Number{}, Number{5}, Number{5}, __LINE__},
261 {Number{5}, Number{}, Number{5}, __LINE__},
262 {Number{5'555'555'555'555'555, -32768},
263 Number{-5'555'555'555'555'554, -32768},
264 Number{0},
265 __LINE__},
266 {Number{-9'999'999'999'999'999, -31},
267 Number{1'000'000'000'000'000, -15},
268 Number{9'999'999'999'999'990, -16},
269 __LINE__},
270 });
271 auto const cLarge = std::to_array<Case>(
272 // Note that items with extremely large mantissas need to be
273 // calculated, because otherwise they overflow uint64. Items from C
274 // with larger mantissa
275 {
276 {Number{1'000'000'000'000'000, -15},
277 Number{6'555'555'555'555'555, -29},
278 Number{1'000'000'000'000'065'556, -18},
279 __LINE__},
280 {Number{-1'000'000'000'000'000, -15},
281 Number{-6'555'555'555'555'555, -29},
282 Number{-1'000'000'000'000'065'556, -18},
283 __LINE__},
284 {Number{-1'000'000'000'000'000, -15},
285 Number{6'555'555'555'555'555, -29},
286 Number{true, 9'999'999'999'999'344'444ULL, -19, Number::Normalized{}},
287 __LINE__},
288 {Number{-6'555'555'555'555'555, -29},
289 Number{1'000'000'000'000'000, -15},
290 Number{false, 9'999'999'999'999'344'444ULL, -19, Number::Normalized{}},
291 __LINE__},
292 {Number{}, Number{5}, Number{5}, __LINE__},
293 {Number{5}, Number{}, Number{5}, __LINE__},
294 {Number{5'555'555'555'555'555'000, -32768},
295 Number{-5'555'555'555'555'554'000, -32768},
296 Number{0},
297 __LINE__},
298 {Number{-9'999'999'999'999'999, -31},
299 Number{1'000'000'000'000'000, -15},
300 Number{9'999'999'999'999'990, -16},
301 __LINE__},
302 // Items from cSmall expanded for the larger mantissa
303 {Number{1'000'000'000'000'000'000, -18},
304 Number{6'555'555'555'555'555'555, -35},
305 Number{1'000'000'000'000'000'066, -18},
306 __LINE__},
307 {Number{-1'000'000'000'000'000'000, -18},
308 Number{-6'555'555'555'555'555'555, -35},
309 Number{-1'000'000'000'000'000'066, -18},
310 __LINE__},
311 {Number{-1'000'000'000'000'000'000, -18},
312 Number{6'555'555'555'555'555'555, -35},
313 Number{true, 9'999'999'999'999'999'344ULL, -19, Number::Normalized{}},
314 __LINE__},
315 {Number{-6'555'555'555'555'555'555, -35},
316 Number{1'000'000'000'000'000'000, -18},
317 Number{false, 9'999'999'999'999'999'344ULL, -19, Number::Normalized{}},
318 __LINE__},
319 {Number{}, Number{5}, Number{5}, __LINE__},
320 {Number{5'555'555'555'555'555'555, -32768},
321 Number{-5'555'555'555'555'555'554, -32768},
322 Number{0},
323 __LINE__},
324 {Number{true, 9'999'999'999'999'999'999ULL, -37, Number::Normalized{}},
325 Number{1'000'000'000'000'000'000, -18},
326 Number{false, 9'999'999'999'999'999'990ULL, -19, Number::Normalized{}},
327 __LINE__},
328 {Number{Number::kMaxRep - 1}, Number{1, 0}, Number{Number::kMaxRep}, __LINE__},
329 // Test extremes
330 {
331 // Each Number operand rounds up, so the actual mantissa is
332 // minMantissa
333 Number{false, 9'999'999'999'999'999'999ULL, 0, Number::Normalized{}},
334 Number{false, 9'999'999'999'999'999'999ULL, 0, Number::Normalized{}},
335 Number{2, 19},
336 __LINE__,
337 },
338 {
339 // Does not round. Mantissas are going to be > kMaxRep, so if
340 // added together as uint64_t's, the result will overflow.
341 // With addition using uint128_t, there's no problem. After
342 // normalizing, the resulting mantissa ends up less than
343 // kMaxRep.
344 Number{false, 9'999'999'999'999'999'990ULL, 0, Number::Normalized{}},
345 Number{false, 9'999'999'999'999'999'990ULL, 0, Number::Normalized{}},
346 Number{false, 1'999'999'999'999'999'998ULL, 1, Number::Normalized{}},
347 __LINE__,
348 },
349 });
350 auto const cLargeLegacy = std::to_array<Case>({
351 {Number{Number::kMaxRep}, Number{6, -1}, Number{Number::kMaxRep / 10, 1}, __LINE__},
352 });
353 auto const cLarge320 = std::to_array<Case>({
355 Number{6, -1},
356 Number{(Number::kMaxRep / 10) + 1, 1},
357 __LINE__},
358 });
359 auto const cLargeCorrected = std::to_array<Case>({
360 {Number{Number::kMaxRep}, Number{6, -1}, Number{Number::kMaxRep}, __LINE__},
361 });
362 auto test = [](auto const& c) {
363 for (auto const& [x, y, z, line] : c)
364 {
365 auto const result = x + y;
367 ss << x << " + " << y << " = " << result << ". Expected: " << z;
368 EXPECT_EQ(result, z) << ss.str() << " Line: " << line;
369 }
370 };
372 {
373 test(cSmall);
374 }
375 else
376 {
377 test(cLarge);
379 {
380 test(cLargeLegacy);
381 }
383 {
384 test(cLarge320);
385 }
386 else
387 {
388 test(cLargeCorrected);
389
390 // This has to be created in this block, because normalization with the other
391 // scales, including the older large mantissa scales, will overflow.
392 Number const bigResult{
394 auto const cBigNums = std::to_array<Case>({
395 {
396 // Add 3 to the mantissa to avoid rounding
397 Number::max(),
399 bigResult,
400 __LINE__,
401 },
402 });
403 test(cBigNums);
404 }
405 }
406 {
407 bool caught = false;
408 try
409 {
410 Number{false, Number::maxMantissa(), 32768, Number::Normalized{}} +
411 Number{false, Number::minMantissa(), 32767, Number::Normalized{}} * 5;
412 }
413 catch (std::overflow_error const&)
414 {
415 caught = true;
416 }
417 EXPECT_TRUE(caught);
418 }
419 }
420}
421
422TEST(NumberTest, add_sub_extreme_exponents)
423{
424 for (auto const mantissaScale : MantissaRange::getAllScales())
425 {
426 NumberMantissaScaleGuard const sg(mantissaScale);
427
428 auto const scale = Number::getMantissaScale();
429
432
433 // Special cases: Exponents at each end of the allowable range
434 for (auto const round :
439 {
440 NumberRoundModeGuard const rg{round};
441
442 auto const bigMantissa = std::invoke([scale, round] {
443 auto m = Number::maxMantissa();
445 {
446 // At the large scales, the maxMantissa is not representable, so we need to
447 // shrink it down to a representable value.
448 m /= 10;
449 }
450 if (round == Number::RoundingMode::Upward)
451 {
452 // Rounding upward will overflow if the mantissa is at maxMantissa. Subtract an
453 // arbitrary small value to keep the mantissa near the limit, but with a
454 // little room to grow. 67 has no meaning, except that it's, you know,
455 // six seven.
456 m -= 67;
457 }
458 return m;
459 });
460 auto const params = {
462 // At the large scales, the maxMantissa is not representable, so we need to shrink
463 // it down to a representable value. Rounding upward will overflow if the mantissa
464 // is right at the all nines value. To keep things a little simpler, do those
465 // modifications unconditionally.
466 std::make_pair(bigMantissa, 1),
467 };
468 for (auto const& [mantissa, exponentOffset] : params)
469 {
470 auto const x = Number{mantissa, Number::kMaxExponent, Number::Normalized{}};
471 auto const y =
472 Number{mantissa, Number::kMinExponent + exponentOffset, Number::Normalized{}};
473
475 detail << "Scale: " << to_string(scale) << ", round: " << to_string(round)
476 << ", x: " << x << ", y: " << y;
477
478 EXPECT_EQ(x.mantissa(), mantissa);
479 EXPECT_EQ(x.exponent(), Number::kMaxExponent);
480 EXPECT_NE(x, beast::kZero);
481 EXPECT_EQ(y.mantissa(), mantissa);
482 EXPECT_EQ(y.exponent(), Number::kMinExponent + exponentOffset);
483 EXPECT_NE(y, beast::kZero);
484
485 {
486 // x + y
487 auto const result = x + y;
488
489 if (round == Number::RoundingMode::Upward)
490 {
491 // Rounding upward will take that little x-bit and round result up to the
492 // next representable value.
493 EXPECT_NE(result, x);
494 EXPECT_EQ(result, (Number{x.mantissa() + 1, x.exponent()}));
495 }
496 else
497 {
498 EXPECT_EQ(result, x);
499 }
500 }
501 {
502 // x - y
503 auto const result = x - y;
504
505 switch (round)
506 {
509 {
510 // Rounding TowardsZero was broken before Large330.
511 EXPECT_EQ(result, x) << detail.str();
512 break;
513 }
514 [[fallthrough]];
516 // Rounding downward (or toward zero in Large330) will take that little
517 // x-bit and round result down to the next representable value.
518 EXPECT_NE(result, x) << detail.str();
519 EXPECT_EQ(result, (Number{x.mantissa() - 1, x.exponent()}))
520 << detail.str();
521 break;
522 default:
523 // Rounding up and toNearest rounds back to the original value
524 EXPECT_EQ(result, x) << detail.str();
525 }
526 }
527 {
528 // y + x
529 auto const result = y + x;
530
531 if (round == Number::RoundingMode::Upward)
532 {
533 // Rounding upward will take that little x-bit and round result up to the
534 // next representable value.
535 EXPECT_NE(result, x);
536 EXPECT_EQ(result, (Number{x.mantissa() + 1, x.exponent()}));
537 }
538 else
539 {
540 EXPECT_EQ(result, x);
541 }
542 }
543 {
544 // y - x
545 auto const result = y - x;
546
547 switch (round)
548 {
551 {
552 // Rounding TowardsZero was broken before Large330.
553 EXPECT_EQ(result, -x) << detail.str();
554 break;
555 }
556 [[fallthrough]];
558 // Rounding upward (or toward zero in Large330) will take that little
559 // x-bit and round result up to the next representable negative value.
560 EXPECT_NE(result, -x) << detail.str();
561 EXPECT_EQ(result, (Number{-x.mantissa() + 1, x.exponent()}))
562 << detail.str();
563 break;
564 default:
565 // Rounding up and toNearest rounds back to the original value
566 EXPECT_EQ(result, -x) << detail.str();
567 }
568 }
569 }
570 }
571 }
572}
573
574TEST(NumberTest, sub)
575{
576 for (auto const mantissaScale : MantissaRange::getAllScales())
577 {
578 NumberMantissaScaleGuard const sg(mantissaScale);
579
580 auto const scale = Number::getMantissaScale();
581
583 auto const cSmall = std::to_array<Case>(
584 {{Number{1'000'000'000'000'000, -15},
585 Number{6'555'555'555'555'555, -29},
586 Number{9'999'999'999'999'344, -16},
587 __LINE__},
588 {Number{6'555'555'555'555'555, -29},
589 Number{1'000'000'000'000'000, -15},
590 Number{-9'999'999'999'999'344, -16},
591 __LINE__},
592 {Number{1'000'000'000'000'000, -15},
593 Number{1'000'000'000'000'000, -15},
594 Number{0},
595 __LINE__},
596 {Number{1'000'000'000'000'000, -15},
597 Number{1'000'000'000'000'001, -15},
598 Number{-1'000'000'000'000'000, -30},
599 __LINE__},
600 {Number{1'000'000'000'000'001, -15},
601 Number{1'000'000'000'000'000, -15},
602 Number{1'000'000'000'000'000, -30},
603 __LINE__}});
604 auto const cLargeAll = std::to_array<Case>(
605 // Note that items with extremely large mantissas need to be
606 // calculated, because otherwise they overflow uint64. Items from C
607 // with larger mantissa
608 {
609 {Number{1'000'000'000'000'000, -15},
610 Number{6'555'555'555'555'555, -29},
611 Number{false, 9'999'999'999'999'344'444ULL, -19, Number::Normalized{}},
612 __LINE__},
613 {Number{6'555'555'555'555'555, -29},
614 Number{1'000'000'000'000'000, -15},
615 Number{true, 9'999'999'999'999'344'444ULL, -19, Number::Normalized{}},
616 __LINE__},
617 {Number{1'000'000'000'000'000, -15},
618 Number{1'000'000'000'000'000, -15},
619 Number{0},
620 __LINE__},
621 {Number{1'000'000'000'000'000, -15},
622 Number{1'000'000'000'000'001, -15},
623 Number{-1'000'000'000'000'000, -30},
624 __LINE__},
625 {Number{1'000'000'000'000'001, -15},
626 Number{1'000'000'000'000'000, -15},
627 Number{1'000'000'000'000'000, -30},
628 __LINE__},
629 // Items from cSmall expanded for the larger mantissa
630 {Number{1'000'000'000'000'000'000, -18},
631 Number{6'555'555'555'555'555'555, -32},
632 Number{false, 9'999'999'999'999'344'444ULL, -19, Number::Normalized{}},
633 __LINE__},
634 {Number{6'555'555'555'555'555'555, -32},
635 Number{1'000'000'000'000'000'000, -18},
636 Number{true, 9'999'999'999'999'344'444ULL, -19, Number::Normalized{}},
637 __LINE__},
638 {Number{1'000'000'000'000'000'000, -18},
639 Number{1'000'000'000'000'000'000, -18},
640 Number{0},
641 __LINE__},
642 {Number{1'000'000'000'000'000'000, -18},
643 Number{1'000'000'000'000'000'001, -18},
644 Number{-1'000'000'000'000'000'000, -36},
645 __LINE__},
646 {Number{1'000'000'000'000'000'001, -18},
647 Number{1'000'000'000'000'000'000, -18},
648 Number{1'000'000'000'000'000'000, -36},
649 __LINE__},
650 {Number{Number::kMaxRep}, Number{6, -1}, Number{Number::kMaxRep - 1}, __LINE__},
651 });
652 // Note that items with extremely large mantissas need to be
653 // calculated, because otherwise they overflow uint64. Items from C
654 // with larger mantissa
655 auto const cLarge = std::to_array<Case>({
656 // Anything larger than kMaxRep rounds up
657 {Number{false, Number::kMaxRep + 1, 0, Number::Normalized{}},
658 Number{1, 0},
659 Number{(Number::kMaxRep / 10) + 1, 1},
660 __LINE__},
661 {Number{false, Number::kMaxRep + 1, 0, Number::Normalized{}},
662 Number{3, 0},
664 __LINE__},
665 {Number{false, Number::kMaxRep + 2, 0, Number::Normalized{}},
666 Number{1, 0},
667 Number{(Number::kMaxRep / 10) + 1, 1},
668 __LINE__},
669 {Number{false, Number::kMaxRep + 2, 0, Number::Normalized{}},
670 Number{3, 0},
672 __LINE__},
673 {power(2, 63), Number{3, 0}, Number{Number::kMaxRep}, __LINE__},
674 });
675 auto const cLarge330 = std::to_array<Case>({
676 // kMaxRep + 1 is below the half-way point, so it rounds down to kMaxRep when the Number
677 // is created.
678 {Number{false, Number::kMaxRep + 1, 0, Number::Normalized{}},
679 Number{1, 0},
681 __LINE__},
682 {Number{false, Number::kMaxRep + 1, 0, Number::Normalized{}},
683 Number{3, 0},
685 __LINE__},
686 // kMaxRepUp -1 is above the half-way point, so it rounds up to kMaxRepUp when the
687 // Number is created. Subtracting 1 from that rounds up again. A little non-intuitive.
689 Number{1, 0},
690 Number{(Number::kMaxRep / 10) + 1, 1},
691 __LINE__},
692 // Subtracting 3 gets back down to kMaxRep
694 Number{3, 0},
696 __LINE__},
697 // 2^63 is the same as kMaxRep+1
698 {power(2, 63), Number{3, 0}, Number{Number::kMaxRep - 3}, __LINE__},
699 });
700 auto test = [](auto const& c) {
701 for (auto const& [x, y, z, line] : c)
702 {
703 auto const result = x - y;
705 ss << x << " - " << y << " = " << result << ". Expected: " << z;
706 EXPECT_EQ(result, z) << ss.str() << " Line: " << line;
707 }
708 };
709 switch (scale)
710 {
712 test(cSmall);
713 break;
716 test(cLargeAll);
717 test(cLarge);
718 break;
720 test(cLargeAll);
721 test(cLarge330);
722 break;
723 default:
724 ADD_FAILURE();
725 break;
726 }
727 }
728}
729
730TEST(NumberTest, mul)
731{
732 for (auto const mantissaScale : MantissaRange::getAllScales())
733 {
734 NumberMantissaScaleGuard const sg(mantissaScale);
735
736 auto const scale = Number::getMantissaScale();
737
739 auto test = [](auto const& c) {
740 for (auto const& [x, y, z] : c)
741 {
742 auto const result = x * y;
744 ss << x << " * " << y << " = " << result << ". Expected: " << z;
745 EXPECT_EQ(result, z) << ss.str();
746 }
747 };
748 auto tests = [&](auto const& cSmall, auto const& cLarge) {
750 {
751 test(cSmall);
752 }
753 else
754 {
755 test(cLarge);
756 }
757 };
758 auto const maxMantissa = Number::maxMantissa();
759
761 {
762 auto const cSmall = std::to_array<Case>({
763 {Number{7}, Number{8}, Number{56}},
764 {Number{1414213562373095, -15},
765 Number{1414213562373095, -15},
766 Number{2000000000000000, -15}},
767 {Number{-1414213562373095, -15},
768 Number{1414213562373095, -15},
769 Number{-2000000000000000, -15}},
770 {Number{-1414213562373095, -15},
771 Number{-1414213562373095, -15},
772 Number{2000000000000000, -15}},
773 {Number{3214285714285706, -15},
774 Number{3111111111111119, -15},
775 Number{1000000000000000, -14}},
776 {Number{1000000000000000, -32768}, Number{1000000000000000, -32768}, Number{0}},
777 // Maximum mantissa range
778 {Number{9'999'999'999'999'999, 0},
779 Number{9'999'999'999'999'999, 0},
780 Number{9'999'999'999'999'998, 16}},
781 });
782 auto const cLarge = std::to_array<Case>({
783 // Note that items with extremely large mantissas need to be
784 // calculated, because otherwise they overflow uint64. Items
785 // from C with larger mantissa
786 {Number{7}, Number{8}, Number{56}},
787 {Number{1414213562373095, -15},
788 Number{1414213562373095, -15},
789 Number{1999999999999999862, -18}},
790 {Number{-1414213562373095, -15},
791 Number{1414213562373095, -15},
792 Number{-1999999999999999862, -18}},
793 {Number{-1414213562373095, -15},
794 Number{-1414213562373095, -15},
795 Number{1999999999999999862, -18}},
796 {Number{3214285714285706, -15},
797 Number{3111111111111119, -15},
798 Number{false, 9'999'999'999'999'999'579ULL, -18, Number::Normalized{}}},
799 {Number{1000000000000000000, -32768},
800 Number{1000000000000000000, -32768},
801 Number{0}},
802 // Items from cSmall expanded for the larger mantissa,
803 // except duplicates. Sadly, it looks like sqrt(2)^2 != 2
804 // with higher precision
805 {Number{1414213562373095049, -18},
806 Number{1414213562373095049, -18},
807 Number{2000000000000000001, -18}},
808 {Number{-1414213562373095048, -18},
809 Number{1414213562373095048, -18},
810 Number{-1999999999999999998, -18}},
811 {Number{-1414213562373095048, -18},
812 Number{-1414213562373095049, -18},
813 Number{1999999999999999999, -18}},
814 {Number{3214285714285714278, -18}, Number{3111111111111111119, -18}, Number{10, 0}},
815 // Maximum mantissa range - rounds up to 1e19
816 {Number{false, maxMantissa, 0, Number::Normalized{}},
817 Number{false, maxMantissa, 0, Number::Normalized{}},
818 Number{1, 38}},
819 // Maximum int64 range
822 Number{85'070'591'730'234'615'85, 19}},
823 });
824 tests(cSmall, cLarge);
825 }
827 {
828 auto const cSmall = std::to_array<Case>(
829 {{Number{7}, Number{8}, Number{56}},
830 {Number{1414213562373095, -15},
831 Number{1414213562373095, -15},
832 Number{1999999999999999, -15}},
833 {Number{-1414213562373095, -15},
834 Number{1414213562373095, -15},
835 Number{-1999999999999999, -15}},
836 {Number{-1414213562373095, -15},
837 Number{-1414213562373095, -15},
838 Number{1999999999999999, -15}},
839 {Number{3214285714285706, -15},
840 Number{3111111111111119, -15},
841 Number{9999999999999999, -15}},
842 {Number{1000000000000000, -32768}, Number{1000000000000000, -32768}, Number{0}}});
843 auto const cLarge = std::to_array<Case>(
844 // Note that items with extremely large mantissas need to be
845 // calculated, because otherwise they overflow uint64. Items
846 // from C with larger mantissa
847 {
848 {Number{7}, Number{8}, Number{56}},
849 {Number{1414213562373095, -15},
850 Number{1414213562373095, -15},
851 Number{1999999999999999861, -18}},
852 {Number{-1414213562373095, -15},
853 Number{1414213562373095, -15},
854 Number{-1999999999999999861, -18}},
855 {Number{-1414213562373095, -15},
856 Number{-1414213562373095, -15},
857 Number{1999999999999999861, -18}},
858 {Number{3214285714285706, -15},
859 Number{3111111111111119, -15},
860 Number{false, 9999999999999999579ULL, -18, Number::Normalized{}}},
861 {Number{1000000000000000000, -32768},
862 Number{1000000000000000000, -32768},
863 Number{0}},
864 // Items from cSmall expanded for the larger mantissa,
865 // except duplicates. Sadly, it looks like sqrt(2)^2 != 2
866 // with higher precision
867 {Number{1414213562373095049, -18},
868 Number{1414213562373095049, -18},
869 Number{2, 0}},
870 {Number{-1414213562373095048, -18},
871 Number{1414213562373095048, -18},
872 Number{-1999999999999999997, -18}},
873 {Number{-1414213562373095048, -18},
874 Number{-1414213562373095049, -18},
875 Number{1999999999999999999, -18}},
876 {Number{3214285714285714278, -18},
877 Number{3111111111111111119, -18},
878 Number{10, 0}},
879 // Maximum mantissa range - rounds down to maxMantissa/10e1
880 // 99'999'999'999'999'999'800'000'000'000'000'000'100
881 {Number{false, maxMantissa, 0, Number::Normalized{}},
882 Number{false, maxMantissa, 0, Number::Normalized{}},
883 Number{false, (maxMantissa / 10) - 1, 20, Number::Normalized{}}},
884 // Maximum int64 range
885 // 85'070'591'730'234'615'847'396'907'784'232'501'249
888 Number{85'070'591'730'234'615'84, 19}},
889 });
890 tests(cSmall, cLarge);
891 }
893 {
894 auto const cSmall = std::to_array<Case>(
895 {{Number{7}, Number{8}, Number{56}},
896 {Number{1414213562373095, -15},
897 Number{1414213562373095, -15},
898 Number{1999999999999999, -15}},
899 {Number{-1414213562373095, -15},
900 Number{1414213562373095, -15},
901 Number{-2000000000000000, -15}},
902 {Number{-1414213562373095, -15},
903 Number{-1414213562373095, -15},
904 Number{1999999999999999, -15}},
905 {Number{3214285714285706, -15},
906 Number{3111111111111119, -15},
907 Number{9999999999999999, -15}},
908 {Number{1000000000000000, -32768}, Number{1000000000000000, -32768}, Number{0}}});
909 auto const cLarge = std::to_array<Case>(
910 // Note that items with extremely large mantissas need to be
911 // calculated, because otherwise they overflow uint64. Items
912 // from C with larger mantissa
913 {
914 {Number{7}, Number{8}, Number{56}},
915 {Number{1414213562373095, -15},
916 Number{1414213562373095, -15},
917 Number{1999999999999999861, -18}},
918 {Number{-1414213562373095, -15},
919 Number{1414213562373095, -15},
920 Number{-1999999999999999862, -18}},
921 {Number{-1414213562373095, -15},
922 Number{-1414213562373095, -15},
923 Number{1999999999999999861, -18}},
924 {Number{3214285714285706, -15},
925 Number{3111111111111119, -15},
926 Number{false, 9'999'999'999'999'999'579ULL, -18, Number::Normalized{}}},
927 {Number{1000000000000000000, -32768},
928 Number{1000000000000000000, -32768},
929 Number{0}},
930 // Items from cSmall expanded for the larger mantissa,
931 // except duplicates. Sadly, it looks like sqrt(2)^2 != 2
932 // with higher precision
933 {Number{1414213562373095049, -18},
934 Number{1414213562373095049, -18},
935 Number{2, 0}},
936 {Number{-1414213562373095048, -18},
937 Number{1414213562373095048, -18},
938 Number{-1999999999999999998, -18}},
939 {Number{-1414213562373095048, -18},
940 Number{-1414213562373095049, -18},
941 Number{1999999999999999999, -18}},
942 {Number{3214285714285714278, -18},
943 Number{3111111111111111119, -18},
944 Number{10, 0}},
945 // Maximum mantissa range - rounds down to maxMantissa/10e1
946 // 99'999'999'999'999'999'800'000'000'000'000'000'100
947 {Number{false, maxMantissa, 0, Number::Normalized{}},
948 Number{false, maxMantissa, 0, Number::Normalized{}},
949 Number{false, (maxMantissa / 10) - 1, 20, Number::Normalized{}}},
950 // Maximum int64 range
951 // 85'070'591'730'234'615'847'396'907'784'232'501'249
954 Number{85'070'591'730'234'615'84, 19}},
955 });
956 tests(cSmall, cLarge);
957 }
959 {
960 auto const cSmall = std::to_array<Case>(
961 {{Number{7}, Number{8}, Number{56}},
962 {Number{1414213562373095, -15},
963 Number{1414213562373095, -15},
964 Number{2000000000000000, -15}},
965 {Number{-1414213562373095, -15},
966 Number{1414213562373095, -15},
967 Number{-1999999999999999, -15}},
968 {Number{-1414213562373095, -15},
969 Number{-1414213562373095, -15},
970 Number{2000000000000000, -15}},
971 {Number{3214285714285706, -15},
972 Number{3111111111111119, -15},
973 Number{1000000000000000, -14}},
974 {Number{1000000000000000, -32768}, Number{1000000000000000, -32768}, Number{0}}});
975 auto const cLarge = std::to_array<Case>(
976 // Note that items with extremely large mantissas need to be
977 // calculated, because otherwise they overflow uint64. Items
978 // from C with larger mantissa
979 {
980 {Number{7}, Number{8}, Number{56}},
981 {Number{1414213562373095, -15},
982 Number{1414213562373095, -15},
983 Number{1999999999999999862, -18}},
984 {Number{-1414213562373095, -15},
985 Number{1414213562373095, -15},
986 Number{-1999999999999999861, -18}},
987 {Number{-1414213562373095, -15},
988 Number{-1414213562373095, -15},
989 Number{1999999999999999862, -18}},
990 {Number{3214285714285706, -15},
991 Number{3111111111111119, -15},
992 Number{999999999999999958, -17}},
993 {Number{1000000000000000000, -32768},
994 Number{1000000000000000000, -32768},
995 Number{0}},
996 // Items from cSmall expanded for the larger mantissa,
997 // except duplicates. Sadly, it looks like sqrt(2)^2 != 2
998 // with higher precision
999 {Number{1414213562373095049, -18},
1000 Number{1414213562373095049, -18},
1001 Number{2000000000000000001, -18}},
1002 {Number{-1414213562373095048, -18},
1003 Number{1414213562373095048, -18},
1004 Number{-1999999999999999997, -18}},
1005 {Number{-1414213562373095048, -18},
1006 Number{-1414213562373095049, -18},
1007 Number{2, 0}},
1008 {Number{3214285714285714278, -18},
1009 Number{3111111111111111119, -18},
1010 Number{1000000000000000001, -17}},
1011 // Maximum mantissa range - rounds up to minMantissa*10
1012 // 1e19*1e19=1e38
1013 {Number{false, maxMantissa, 0, Number::Normalized{}},
1014 Number{false, maxMantissa, 0, Number::Normalized{}},
1015 Number{1, 38}},
1016 // Maximum int64 range
1017 // 85'070'591'730'234'615'847'396'907'784'232'501'249
1020 Number{85'070'591'730'234'615'85, 19}},
1021 });
1022 tests(cSmall, cLarge);
1023 }
1024 {
1025 bool caught = false;
1026 try
1027 {
1028 Number{false, maxMantissa, 32768, Number::Normalized{}} *
1029 Number{false, Number::minMantissa() * 5, 32767, Number::Normalized{}};
1030 }
1031 catch (std::overflow_error const&)
1032 {
1033 caught = true;
1034 }
1035 EXPECT_TRUE(caught);
1036 }
1037 }
1038}
1039
1040TEST(NumberTest, div)
1041{
1042 for (auto const mantissaScale : MantissaRange::getAllScales())
1043 {
1044 NumberMantissaScaleGuard const sg(mantissaScale);
1045
1046 auto const scale = Number::getMantissaScale();
1047
1049 auto test = [](auto const& c) {
1050 for (auto const& [x, y, z] : c)
1051 {
1052 auto const result = x / y;
1054 ss << x << " / " << y << " = " << result << ". Expected: " << z;
1055 EXPECT_EQ(result, z) << ss.str();
1056 }
1057 };
1058 auto const maxMantissa = Number::maxMantissa();
1059 auto tests = [&](auto const& cSmall, auto const& cLarge) {
1061 {
1062 test(cSmall);
1063 }
1064 else
1065 {
1066 test(cLarge);
1067 }
1068 };
1070 {
1071 auto const cSmall = std::to_array<Case>(
1072 {{Number{1}, Number{2}, Number{5, -1}},
1073 {Number{1}, Number{10}, Number{1, -1}},
1074 {Number{1}, Number{-10}, Number{-1, -1}},
1075 {Number{0}, Number{100}, Number{0}},
1076 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
1077 {Number{9'999'999'999'999'999},
1078 Number{1'000'000'000'000'000},
1079 Number{9'999'999'999'999'999, -15}},
1080 {Number{2}, Number{3}, Number{6'666'666'666'666'667, -16}},
1081 {Number{-2}, Number{3}, Number{-6'666'666'666'666'667, -16}},
1082 {Number{1}, Number{7}, Number{1'428'571'428'571'428, -16}}});
1083 auto const cLarge = std::to_array<Case>(
1084 // Note that items with extremely large mantissas need to be
1085 // calculated, because otherwise they overflow uint64. Items
1086 // from C with larger mantissa
1087 {{Number{1}, Number{2}, Number{5, -1}},
1088 {Number{1}, Number{10}, Number{1, -1}},
1089 {Number{1}, Number{-10}, Number{-1, -1}},
1090 {Number{0}, Number{100}, Number{0}},
1091 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
1092 {Number{9'999'999'999'999'999},
1093 Number{1'000'000'000'000'000},
1094 Number{9'999'999'999'999'999, -15}},
1095 {Number{2}, Number{3}, Number{6'666'666'666'666'666'667, -19}},
1096 {Number{-2}, Number{3}, Number{-6'666'666'666'666'666'667, -19}},
1097 {Number{1}, Number{7}, Number{1'428'571'428'571'428'571, -19}},
1098 // Items from cSmall expanded for the larger mantissa, except
1099 // duplicates.
1100 {Number{1414213562373095049, -13}, Number{1414213562373095049, -13}, Number{1}},
1101 {Number{false, maxMantissa, 0, Number::Normalized{}},
1102 Number{1'000'000'000'000'000'000},
1103 Number{false, maxMantissa, -18, Number::Normalized{}}}});
1104 tests(cSmall, cLarge);
1105 }
1107 {
1108 auto const cSmall = std::to_array<Case>(
1109 {{Number{1}, Number{2}, Number{5, -1}},
1110 {Number{1}, Number{10}, Number{1, -1}},
1111 {Number{1}, Number{-10}, Number{-1, -1}},
1112 {Number{0}, Number{100}, Number{0}},
1113 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
1114 {Number{9'999'999'999'999'999},
1115 Number{1'000'000'000'000'000},
1116 Number{9'999'999'999'999'999, -15}},
1117 {Number{2}, Number{3}, Number{6'666'666'666'666'666, -16}},
1118 {Number{-2}, Number{3}, Number{-6'666'666'666'666'666, -16}},
1119 {Number{1}, Number{7}, Number{1'428'571'428'571'428, -16}}});
1120 auto const cLarge = std::to_array<Case>(
1121 // Note that items with extremely large mantissas need to be
1122 // calculated, because otherwise they overflow uint64. Items
1123 // from C with larger mantissa
1124 {{Number{1}, Number{2}, Number{5, -1}},
1125 {Number{1}, Number{10}, Number{1, -1}},
1126 {Number{1}, Number{-10}, Number{-1, -1}},
1127 {Number{0}, Number{100}, Number{0}},
1128 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
1129 {Number{9'999'999'999'999'999},
1130 Number{1'000'000'000'000'000},
1131 Number{9'999'999'999'999'999, -15}},
1132 {Number{2}, Number{3}, Number{6'666'666'666'666'666'666, -19}},
1133 {Number{-2}, Number{3}, Number{-6'666'666'666'666'666'666, -19}},
1134 {Number{1}, Number{7}, Number{1'428'571'428'571'428'571, -19}},
1135 // Items from cSmall expanded for the larger mantissa, except
1136 // duplicates.
1137 {Number{1414213562373095049, -13}, Number{1414213562373095049, -13}, Number{1}},
1138 {Number{false, maxMantissa, 0, Number::Normalized{}},
1139 Number{1'000'000'000'000'000'000},
1140 Number{false, maxMantissa, -18, Number::Normalized{}}}});
1141 tests(cSmall, cLarge);
1142 }
1144 {
1145 auto const cSmall = std::to_array<Case>(
1146 {{Number{1}, Number{2}, Number{5, -1}},
1147 {Number{1}, Number{10}, Number{1, -1}},
1148 {Number{1}, Number{-10}, Number{-1, -1}},
1149 {Number{0}, Number{100}, Number{0}},
1150 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
1151 {Number{9'999'999'999'999'999},
1152 Number{1'000'000'000'000'000},
1153 Number{9'999'999'999'999'999, -15}},
1154 {Number{2}, Number{3}, Number{6'666'666'666'666'666, -16}},
1155 {Number{-2}, Number{3}, Number{-6'666'666'666'666'667, -16}},
1156 {Number{1}, Number{7}, Number{1'428'571'428'571'428, -16}}});
1157 auto const cLarge = std::to_array<Case>(
1158 // Note that items with extremely large mantissas need to be
1159 // calculated, because otherwise they overflow uint64. Items
1160 // from C with larger mantissa
1161 {{Number{1}, Number{2}, Number{5, -1}},
1162 {Number{1}, Number{10}, Number{1, -1}},
1163 {Number{1}, Number{-10}, Number{-1, -1}},
1164 {Number{0}, Number{100}, Number{0}},
1165 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
1166 {Number{9'999'999'999'999'999},
1167 Number{1'000'000'000'000'000},
1168 Number{9'999'999'999'999'999, -15}},
1169 {Number{2}, Number{3}, Number{6'666'666'666'666'666'666, -19}},
1170 {Number{-2}, Number{3}, Number{-6'666'666'666'666'666'667, -19}},
1171 {Number{1}, Number{7}, Number{1'428'571'428'571'428'571, -19}},
1172 // Items from cSmall expanded for the larger mantissa, except
1173 // duplicates.
1174 {Number{1414213562373095049, -13}, Number{1414213562373095049, -13}, Number{1}},
1175 {Number{false, maxMantissa, 0, Number::Normalized{}},
1176 Number{1'000'000'000'000'000'000},
1177 Number{false, maxMantissa, -18, Number::Normalized{}}}});
1178 tests(cSmall, cLarge);
1179 }
1181 {
1182 auto const cSmall = std::to_array<Case>(
1183 {{Number{1}, Number{2}, Number{5, -1}},
1184 {Number{1}, Number{10}, Number{1, -1}},
1185 {Number{1}, Number{-10}, Number{-1, -1}},
1186 {Number{0}, Number{100}, Number{0}},
1187 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
1188 {Number{9'999'999'999'999'999},
1189 Number{1'000'000'000'000'000},
1190 Number{9'999'999'999'999'999, -15}},
1191 {Number{2}, Number{3}, Number{6'666'666'666'666'667, -16}},
1192 {Number{-2}, Number{3}, Number{-6'666'666'666'666'666, -16}},
1193 {Number{1}, Number{7}, Number{1'428'571'428'571'429, -16}}});
1194 auto const cLarge = std::to_array<Case>(
1195 // Note that items with extremely large mantissas need to be
1196 // calculated, because otherwise they overflow uint64. Items
1197 // from C with larger mantissa
1198 {{Number{1}, Number{2}, Number{5, -1}},
1199 {Number{1}, Number{10}, Number{1, -1}},
1200 {Number{1}, Number{-10}, Number{-1, -1}},
1201 {Number{0}, Number{100}, Number{0}},
1202 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
1203 {Number{9'999'999'999'999'999},
1204 Number{1'000'000'000'000'000},
1205 Number{9'999'999'999'999'999, -15}},
1206 {Number{2}, Number{3}, Number{6'666'666'666'666'666'667, -19}},
1207 {Number{-2}, Number{3}, Number{-6'666'666'666'666'666'666, -19}},
1208 {Number{1}, Number{7}, Number{1'428'571'428'571'428'572, -19}},
1209 // Items from cSmall expanded for the larger mantissa, except
1210 // duplicates.
1211 {Number{1414213562373095049, -13}, Number{1414213562373095049, -13}, Number{1}},
1212 {Number{false, maxMantissa, 0, Number::Normalized{}},
1213 Number{1'000'000'000'000'000'000},
1214 Number{false, maxMantissa, -18, Number::Normalized{}}}});
1215 tests(cSmall, cLarge);
1216 }
1217 bool caught = false;
1218 try
1219 {
1220 Number{1000000000000000, -15} / Number{0};
1221 }
1222 catch (std::overflow_error const&)
1223 {
1224 caught = true;
1225 }
1226 EXPECT_TRUE(caught);
1227 }
1228}
1229
1230TEST(NumberTest, root)
1231{
1232 for (auto const mantissaScale : MantissaRange::getAllScales())
1233 {
1234 NumberMantissaScaleGuard const sg(mantissaScale);
1235
1237 auto test = [](auto const& c) {
1238 for (auto const& [x, y, z] : c)
1239 {
1240 auto const result = root(x, y);
1242 ss << "root(" << x << ", " << y << ") = " << result << ". Expected: " << z;
1243 EXPECT_EQ(result, z) << ss.str();
1244 }
1245 };
1246 auto const cSmall = std::to_array<Case>(
1247 {{Number{2}, 2, Number{1414213562373095049, -18}},
1248 {Number{2'000'000}, 2, Number{1414213562373095049, -15}},
1249 {Number{2, -30}, 2, Number{1414213562373095049, -33}},
1250 {Number{-27}, 3, Number{-3}},
1251 {Number{1}, 5, Number{1}},
1252 {Number{-1}, 0, Number{1}},
1253 {Number{5, -1}, 0, Number{0}},
1254 {Number{0}, 5, Number{0}},
1255 {Number{5625, -4}, 2, Number{75, -2}}});
1256 auto const cLarge = std::to_array<Case>({
1257 {Number{false, Number::maxMantissa() - 9, -1, Number::Normalized{}},
1258 2,
1259 Number{false, 999'999'999'999'999'999, -9, Number::Normalized{}}},
1260 {Number{false, Number::maxMantissa() - 9, 0, Number::Normalized{}},
1261 2,
1262 Number{false, 3'162'277'660'168'379'330, -9, Number::Normalized{}}},
1264 2,
1265 Number{false, 3'037'000'499'976049692, -9, Number::Normalized{}}},
1267 4,
1268 Number{false, 55'108'98747006743627, -14, Number::Normalized{}}},
1269 });
1270 test(cSmall);
1272 {
1274 test(cLarge);
1275 }
1276 bool caught = false;
1277 try
1278 {
1279 (void)root(Number{-2}, 0);
1280 }
1281 catch (std::overflow_error const&)
1282 {
1283 caught = true;
1284 }
1285 EXPECT_TRUE(caught);
1286 caught = false;
1287 try
1288 {
1289 (void)root(Number{-2}, 4);
1290 }
1291 catch (std::overflow_error const&)
1292 {
1293 caught = true;
1294 }
1295 EXPECT_TRUE(caught);
1296 }
1297}
1298
1299TEST(NumberTest, root2)
1300{
1301 for (auto const mantissaScale : MantissaRange::getAllScales())
1302 {
1303 NumberMantissaScaleGuard const sg(mantissaScale);
1304
1305 auto test = [](auto const& c) {
1306 for (auto const& x : c)
1307 {
1308 auto const expected = root(x, 2);
1309 auto const result = root2(x);
1311 ss << "root2(" << x << ") = " << result << ". Expected: " << expected;
1312 EXPECT_EQ(result, expected) << ss.str();
1313 }
1314 };
1315
1316 auto const cSmall = std::to_array<Number>({
1317 Number{2},
1318 Number{2'000'000},
1319 Number{2, -30},
1320 Number{27},
1321 Number{1},
1322 Number{5, -1},
1323 Number{0},
1324 Number{5625, -4},
1326 });
1327 test(cSmall);
1328 bool caught = false;
1329 try
1330 {
1331 (void)root2(Number{-2});
1332 }
1333 catch (std::overflow_error const&)
1334 {
1335 caught = true;
1336 }
1337 EXPECT_TRUE(caught);
1338 }
1339}
1340
1341TEST(NumberTest, power1)
1342{
1343 for (auto const mantissaScale : MantissaRange::getAllScales())
1344 {
1345 NumberMantissaScaleGuard const sg(mantissaScale);
1346
1348 Case const c[]{
1349 {Number{64}, 0, Number{1}},
1350 {Number{64}, 1, Number{64}},
1351 {Number{64}, 2, Number{4096}},
1352 {Number{-64}, 2, Number{4096}},
1353 {Number{64}, 3, Number{262144}},
1354 {Number{-64}, 3, Number{-262144}},
1355 {Number{64}, 11, Number{false, 7378697629483820646ULL, 1, Number::Normalized{}}},
1356 {Number{-64}, 11, Number{true, 7378697629483820646ULL, 1, Number::Normalized{}}}};
1357 for (auto const& [x, y, z] : c)
1358 EXPECT_EQ(power(x, y), z);
1359 }
1360}
1361
1362TEST(NumberTest, power2)
1363{
1364 for (auto const mantissaScale : MantissaRange::getAllScales())
1365 {
1366 NumberMantissaScaleGuard const sg(mantissaScale);
1367
1369 Case const c[]{
1370 {Number{1}, 3, 7, Number{1}},
1371 {Number{-1}, 1, 0, Number{1}},
1372 {Number{-1, -1}, 1, 0, Number{0}},
1373 {Number{16}, 0, 5, Number{1}},
1374 {Number{34}, 3, 3, Number{34}},
1375 {Number{4}, 3, 2, Number{8}}};
1376 for (auto const& [x, n, d, z] : c)
1377 EXPECT_EQ(power(x, n, d), z);
1378 bool caught = false;
1379 try
1380 {
1381 (void)power(Number{7}, 0, 0);
1382 }
1383 catch (std::overflow_error const&)
1384 {
1385 caught = true;
1386 }
1387 EXPECT_TRUE(caught);
1388 caught = false;
1389 try
1390 {
1391 (void)power(Number{7}, 1, 0);
1392 }
1393 catch (std::overflow_error const&)
1394 {
1395 caught = true;
1396 }
1397 EXPECT_TRUE(caught);
1398 caught = false;
1399 try
1400 {
1401 (void)power(Number{-1, -1}, 3, 2);
1402 }
1403 catch (std::overflow_error const&)
1404 {
1405 caught = true;
1406 }
1407 EXPECT_TRUE(caught);
1408 }
1409}
1410
1411TEST(NumberTest, conversions)
1412{
1413 for (auto const mantissaScale : MantissaRange::getAllScales())
1414 {
1415 NumberMantissaScaleGuard const sg(mantissaScale);
1416
1417 IOUAmount const x{5, 6};
1418 Number const y = x;
1419 EXPECT_EQ(y, (Number{5, 6}));
1420 IOUAmount const z{y};
1421 EXPECT_EQ(x, z);
1422 XRPAmount const xrp{500};
1423 STAmount const st = xrp;
1424 Number const n = st;
1425 EXPECT_EQ(XRPAmount{n}, xrp);
1426 IOUAmount const x0{0, 0};
1427 Number const y0 = x0;
1428 EXPECT_EQ(y0, Number{0});
1429 IOUAmount const z0{y0};
1430 EXPECT_EQ(x0, z0);
1431 XRPAmount const xrp0{0};
1432 Number const n0 = xrp0;
1433 EXPECT_EQ(n0, Number{0});
1434 XRPAmount const xrp1{n0}; // NOLINT misc-confusable-identifiers
1435 EXPECT_EQ(xrp1, xrp0);
1436 }
1437}
1438
1439TEST(NumberTest, to_integer)
1440{
1441 for (auto const mantissaScale : MantissaRange::getAllScales())
1442 {
1443 NumberMantissaScaleGuard const sg(mantissaScale);
1444
1447 {
1448 Case const c[]{
1449 {Number{0}, 0},
1450 {Number{1}, 1},
1451 {Number{2}, 2},
1452 {Number{3}, 3},
1453 {Number{-1}, -1},
1454 {Number{-2}, -2},
1455 {Number{-3}, -3},
1456 {Number{10}, 10},
1457 {Number{99}, 99},
1458 {Number{1155}, 1155},
1459 {Number{9'999'999'999'999'999, 0}, 9'999'999'999'999'999},
1460 {Number{9'999'999'999'999'999, 1}, 99'999'999'999'999'990},
1461 {Number{9'999'999'999'999'999, 2}, 999'999'999'999'999'900},
1462 {Number{-9'999'999'999'999'999, 2}, -999'999'999'999'999'900},
1463 {Number{15, -1}, 2},
1464 {Number{14, -1}, 1},
1465 {Number{16, -1}, 2},
1466 {Number{25, -1}, 2},
1467 {Number{6, -1}, 1},
1468 {Number{5, -1}, 0},
1469 {Number{4, -1}, 0},
1470 {Number{-15, -1}, -2},
1471 {Number{-14, -1}, -1},
1472 {Number{-16, -1}, -2},
1473 {Number{-25, -1}, -2},
1474 {Number{-6, -1}, -1},
1475 {Number{-5, -1}, 0},
1476 {Number{-4, -1}, 0}};
1477 for (auto const& [x, y] : c)
1478 {
1479 auto j = static_cast<std::int64_t>(x);
1480 EXPECT_EQ(j, y);
1481 }
1482 }
1484 EXPECT_EQ(prevMode, Number::RoundingMode::ToNearest);
1485 {
1486 Case const c[]{
1487 {Number{0}, 0},
1488 {Number{1}, 1},
1489 {Number{2}, 2},
1490 {Number{3}, 3},
1491 {Number{-1}, -1},
1492 {Number{-2}, -2},
1493 {Number{-3}, -3},
1494 {Number{10}, 10},
1495 {Number{99}, 99},
1496 {Number{1155}, 1155},
1497 {Number{9'999'999'999'999'999, 0}, 9'999'999'999'999'999},
1498 {Number{9'999'999'999'999'999, 1}, 99'999'999'999'999'990},
1499 {Number{9'999'999'999'999'999, 2}, 999'999'999'999'999'900},
1500 {Number{-9'999'999'999'999'999, 2}, -999'999'999'999'999'900},
1501 {Number{15, -1}, 1},
1502 {Number{14, -1}, 1},
1503 {Number{16, -1}, 1},
1504 {Number{25, -1}, 2},
1505 {Number{6, -1}, 0},
1506 {Number{5, -1}, 0},
1507 {Number{4, -1}, 0},
1508 {Number{-15, -1}, -1},
1509 {Number{-14, -1}, -1},
1510 {Number{-16, -1}, -1},
1511 {Number{-25, -1}, -2},
1512 {Number{-6, -1}, 0},
1513 {Number{-5, -1}, 0},
1514 {Number{-4, -1}, 0}};
1515 for (auto const& [x, y] : c)
1516 {
1517 auto j = static_cast<std::int64_t>(x);
1518 EXPECT_EQ(j, y);
1519 }
1520 }
1522 EXPECT_EQ(prevMode, Number::RoundingMode::TowardsZero);
1523 {
1524 Case const c[]{
1525 {Number{0}, 0},
1526 {Number{1}, 1},
1527 {Number{2}, 2},
1528 {Number{3}, 3},
1529 {Number{-1}, -1},
1530 {Number{-2}, -2},
1531 {Number{-3}, -3},
1532 {Number{10}, 10},
1533 {Number{99}, 99},
1534 {Number{1155}, 1155},
1535 {Number{9'999'999'999'999'999, 0}, 9'999'999'999'999'999},
1536 {Number{9'999'999'999'999'999, 1}, 99'999'999'999'999'990},
1537 {Number{9'999'999'999'999'999, 2}, 999'999'999'999'999'900},
1538 {Number{-9'999'999'999'999'999, 2}, -999'999'999'999'999'900},
1539 {Number{15, -1}, 1},
1540 {Number{14, -1}, 1},
1541 {Number{16, -1}, 1},
1542 {Number{25, -1}, 2},
1543 {Number{6, -1}, 0},
1544 {Number{5, -1}, 0},
1545 {Number{4, -1}, 0},
1546 {Number{-15, -1}, -2},
1547 {Number{-14, -1}, -2},
1548 {Number{-16, -1}, -2},
1549 {Number{-25, -1}, -3},
1550 {Number{-6, -1}, -1},
1551 {Number{-5, -1}, -1},
1552 {Number{-4, -1}, -1}};
1553 for (auto const& [x, y] : c)
1554 {
1555 auto j = static_cast<std::int64_t>(x);
1556 EXPECT_EQ(j, y);
1557 }
1558 }
1560 EXPECT_EQ(prevMode, Number::RoundingMode::Downward);
1561 {
1562 Case const c[]{
1563 {Number{0}, 0},
1564 {Number{1}, 1},
1565 {Number{2}, 2},
1566 {Number{3}, 3},
1567 {Number{-1}, -1},
1568 {Number{-2}, -2},
1569 {Number{-3}, -3},
1570 {Number{10}, 10},
1571 {Number{99}, 99},
1572 {Number{1155}, 1155},
1573 {Number{9'999'999'999'999'999, 0}, 9'999'999'999'999'999},
1574 {Number{9'999'999'999'999'999, 1}, 99'999'999'999'999'990},
1575 {Number{9'999'999'999'999'999, 2}, 999'999'999'999'999'900},
1576 {Number{-9'999'999'999'999'999, 2}, -999'999'999'999'999'900},
1577 {Number{15, -1}, 2},
1578 {Number{14, -1}, 2},
1579 {Number{16, -1}, 2},
1580 {Number{25, -1}, 3},
1581 {Number{6, -1}, 1},
1582 {Number{5, -1}, 1},
1583 {Number{4, -1}, 1},
1584 {Number{-15, -1}, -1},
1585 {Number{-14, -1}, -1},
1586 {Number{-16, -1}, -1},
1587 {Number{-25, -1}, -2},
1588 {Number{-6, -1}, 0},
1589 {Number{-5, -1}, 0},
1590 {Number{-4, -1}, 0}};
1591 for (auto const& [x, y] : c)
1592 {
1593 auto j = static_cast<std::int64_t>(x);
1594 EXPECT_EQ(j, y);
1595 }
1596 }
1597 bool caught = false;
1598 try
1599 {
1600 (void)static_cast<std::int64_t>(Number{9223372036854776, 3});
1601 }
1602 catch (std::overflow_error const&)
1603 {
1604 caught = true;
1605 }
1606 EXPECT_TRUE(caught);
1607 }
1608}
1609
1610TEST(NumberTest, squelch)
1611{
1612 for (auto const mantissaScale : MantissaRange::getAllScales())
1613 {
1614 NumberMantissaScaleGuard const sg(mantissaScale);
1615
1616 Number const limit{1, -6};
1617 EXPECT_EQ(squelch(Number{2, -6}, limit), (Number{2, -6}));
1618 EXPECT_EQ(squelch(Number{1, -6}, limit), (Number{1, -6}));
1619 EXPECT_EQ(squelch(Number{9, -7}, limit), Number{0});
1620 EXPECT_EQ(squelch(Number{-2, -6}, limit), (Number{-2, -6}));
1621 EXPECT_EQ(squelch(Number{-1, -6}, limit), (Number{-1, -6}));
1622 EXPECT_EQ(squelch(Number{-9, -7}, limit), Number{0});
1623 }
1624}
1625
1626TEST(NumberTest, to_string)
1627{
1628 for (auto const mantissaScale : MantissaRange::getAllScales())
1629 {
1630 NumberMantissaScaleGuard const sg(mantissaScale);
1631
1632 auto const scale = Number::getMantissaScale();
1633
1634 auto test = [](Number const& n, std::string const& expected, int line) {
1635 auto const result = to_string(n);
1637 ss << "to_string(" << result << "). Expected: " << expected;
1638 EXPECT_EQ(result, expected) << ss.str() << " Line: " << line;
1639 };
1640
1641 test(Number(-2, 0), "-2", __LINE__);
1642 test(Number(0, 0), "0", __LINE__);
1643 test(Number(2, 0), "2", __LINE__);
1644 test(Number(25, -3), "0.025", __LINE__);
1645 test(Number(-25, -3), "-0.025", __LINE__);
1646 test(Number(25, 1), "250", __LINE__);
1647 test(Number(-25, 1), "-250", __LINE__);
1648 test(Number(2, 20), "2e20", __LINE__);
1649 test(Number(-2, -20), "-2e-20", __LINE__);
1650 // Test the edges
1651 // ((exponent < -(25)) || (exponent > -(5)))))
1652 // or ((exponent < -(28)) || (exponent > -(8)))))
1653 test(Number(2, -10), "0.0000000002", __LINE__);
1654 test(Number(2, -11), "2e-11", __LINE__);
1655
1656 test(Number(-2, 10), "-20000000000", __LINE__);
1657 test(Number(-2, 11), "-2e11", __LINE__);
1658 test(Number(-2, 11) - 1, "-200000000001", __LINE__);
1659
1660 switch (scale)
1661 {
1663
1664 test(Number::min(), "1e-32753", __LINE__);
1665 test(Number::max(), "9999999999999999e32768", __LINE__);
1666 test(Number::lowest(), "-9999999999999999e32768", __LINE__);
1667 {
1669
1670 auto const maxMantissa = Number::maxMantissa();
1671 EXPECT_EQ(maxMantissa, 9'999'999'999'999'999);
1672 test(
1673 Number{false, (maxMantissa * 1000) + 999, -3, Number::Normalized()},
1674 "9999999999999999",
1675 __LINE__);
1676 test(
1677 Number{true, (maxMantissa * 1000) + 999, -3, Number::Normalized()},
1678 "-9999999999999999",
1679 __LINE__);
1680
1681 test(
1683 "9223372036854775",
1684 __LINE__);
1685 test(
1687 "-9223372036854775",
1688 __LINE__);
1689
1690 test(
1692 "-9223372036854775e3",
1693 __LINE__);
1694 test(
1696 "9223372036854775e3",
1697 __LINE__);
1698 }
1699 break;
1700 default:
1701 // Test the edges
1702 // ((exponent < -(28)) || (exponent > -(8)))))
1703 test(Number::min(), "1e-32750", __LINE__);
1704 test(Number::max(), "9223372036854775807e32768", __LINE__);
1705 test(Number::lowest(), "-9223372036854775807e32768", __LINE__);
1706 {
1708
1709 auto const maxMantissa = Number::maxMantissa();
1710 EXPECT_EQ(maxMantissa, 9'999'999'999'999'999'999ULL);
1711 test(
1712 Number{false, maxMantissa, 0, Number::Normalized{}},
1713 "9999999999999999990",
1714 __LINE__);
1715 test(
1716 Number{true, maxMantissa, 0, Number::Normalized{}},
1717 "-9999999999999999990",
1718 __LINE__);
1719
1720 test(
1722 "9223372036854775807",
1723 __LINE__);
1724 test(
1726 "-9223372036854775807",
1727 __LINE__);
1728
1729 switch (scale)
1730 {
1732 // Because the absolute value of min() is larger than max(), it
1733 // will be rounded down toward max()
1734 test(
1736 "-9223372036854775807",
1737 __LINE__);
1738 test(
1740 "9223372036854775807",
1741 __LINE__);
1742 break;
1743 default:
1744 // Because the absolute value of min() is larger than max(), it
1745 // will be scaled down to fit under max(). Since we're
1746 // rounding towards zero, the 8 at the end is dropped.
1747 test(
1749 "-9223372036854775800",
1750 __LINE__);
1751 test(
1753 "9223372036854775800",
1754 __LINE__);
1755 break;
1756 }
1757 }
1758
1759 switch (scale)
1760 {
1762 // Rounding to nearest, since the mantissa is below the halfway point from
1763 // kMaxRep to kMaxRepUp, it will be rounded down to kMaxRep
1764 test(
1766 "9223372036854775807",
1767 __LINE__);
1768 test(
1770 "-9223372036854775807",
1771 __LINE__);
1772 break;
1773 default:
1774 // Rounding to nearest, since the mantissa is bigger than kMaxRep, the 8
1775 // will be dropped, and since that is bigger than 5, the result will be
1776 // rounded up from 0 to 1.
1777 test(
1779 "9223372036854775810",
1780 __LINE__);
1781 test(
1783 "-9223372036854775810",
1784 __LINE__);
1785 break;
1786 }
1787 // Rounding to nearest, will be rounded up to kMaxRepUp, but for different reasons
1788 // depending on the scale. If older than "Large", it rounds up for the same reason
1789 // "+1" rounds up. For "Large", since the mantissa is above the halfway point from
1790 // kMaxRep to kMaxRepUp, it will be rounded up to kMaxRepUp.
1791 test(
1793 "9223372036854775810",
1794 __LINE__);
1795 test(
1797 "-9223372036854775810",
1798 __LINE__);
1799 break;
1800 }
1801 }
1802}
1803
1804TEST(NumberTest, relationals)
1805{
1806 for (auto const mantissaScale : MantissaRange::getAllScales())
1807 {
1808 NumberMantissaScaleGuard const sg(mantissaScale);
1809
1810 {
1811 auto test = [](auto const& nums) {
1812 EXPECT_TRUE(std::ranges::is_sorted(nums));
1813
1814 for (auto iter1 = nums.begin(); iter1 != nums.end(); ++iter1)
1815 {
1816 auto iter2 = iter1;
1817 for (++iter2; iter2 != nums.end(); ++iter2)
1818 {
1819 Number const& smaller = *iter1;
1820 Number const& larger = *iter2;
1822 ss << smaller << " < " << larger;
1823 auto const str = ss.str();
1824
1825 // The ==/!= operators use a completely different code path than <, etc.
1826 // This helps detect a breakage in one but not the other. It also helps
1827 // verify that the values are being ordered correctly.
1828 EXPECT_TRUE(smaller != larger) << str << " (!=)";
1829 EXPECT_FALSE(smaller == larger) << str << " (==)";
1830
1831 // true results using operator< and derived operators
1832 EXPECT_TRUE(smaller < larger) << str << " (<)";
1833 EXPECT_TRUE(larger > smaller) << str << " (>)";
1834 EXPECT_TRUE(larger >= smaller) << str << " (>=)";
1835 EXPECT_TRUE(smaller <= larger) << str << " (<=)";
1836
1837 // false results using operator< and derived operators
1838 EXPECT_FALSE(larger < smaller) << str << " (! <)";
1839 EXPECT_FALSE(smaller > larger) << str << " (! >)";
1840 EXPECT_FALSE(smaller >= larger) << str << " (! >=)";
1841 EXPECT_FALSE(larger <= smaller) << str << " (! <=)";
1842 }
1843 }
1844 };
1845
1846 auto const intNums = []() {
1847 // Inequality test cases are built from a list of sorted integers
1848 auto const values =
1849 std::to_array<int>({-100, -50, -20, -10, -1, 0, 1, 10, 20, 50, 100});
1850 // Check this list is sorted before converting it to Numbers.
1851 // That way if any of the other tests fail, we know it's because of code and not the
1852 // source data.
1853 EXPECT_TRUE(std::ranges::is_sorted(values));
1854
1855 std::vector<Number> result;
1856 result.reserve(values.size());
1857 for (auto const v : values)
1858 result.emplace_back(v);
1859 return result;
1860 }();
1861
1862 auto const otherNums = std::to_array<Number>({
1863 Number{-5, 100},
1864 Number{-1, 100},
1865 Number{-7, -10},
1866 Number{-2, -10},
1867 Number{0},
1868 Number{2, -10},
1869 Number{7, -10},
1870 Number{1, 100},
1871 Number{5, 100},
1872 });
1873
1874 test(intNums);
1875 test(otherNums);
1876 }
1877
1878 {
1879 // Equality test cases are <Number, __LINE__>. Number will be compared against itself
1880 using Case = std::pair<Number, int>;
1881 auto const c = std::to_array<Case>({
1882 {700, __LINE__},
1883 {50, __LINE__},
1884 {1, __LINE__},
1885 {0, __LINE__},
1886 {-1, __LINE__},
1887 {-30, __LINE__},
1888 {-600, __LINE__},
1889 });
1890 for (auto const& [n, line] : c)
1891 {
1892 auto const str = to_string(n);
1893 auto const location =
1894 std::string{" ("} + __FILE__ + ":" + std::to_string(line) + ")";
1895
1896 // NOLINTBEGIN(misc-redundant-expression) Explicitly testing operators with
1897 // equivalent values
1898 EXPECT_TRUE(n == n) << str << " ==" << location;
1899 EXPECT_FALSE(n != n) << str << " !=" << location;
1900
1901 EXPECT_FALSE(n < n) << str << " <" << location;
1902 EXPECT_FALSE(n > n) << str << " >" << location;
1903 EXPECT_TRUE(n >= n) << str << " >=" << location;
1904 EXPECT_TRUE(n <= n) << str << " <=" << location;
1905 // NOLINTEND(misc-redundant-expression)
1906 }
1907 }
1908 }
1909}
1910
1911TEST(NumberTest, stream)
1912{
1913 for (auto const mantissaScale : MantissaRange::getAllScales())
1914 {
1915 NumberMantissaScaleGuard const sg(mantissaScale);
1916
1917 Number const x{100};
1919 os << x;
1920 EXPECT_EQ((os.str()), (to_string(x)));
1921 }
1922}
1923
1924TEST(NumberTest, inc_dec)
1925{
1926 for (auto const mantissaScale : MantissaRange::getAllScales())
1927 {
1928 NumberMantissaScaleGuard const sg(mantissaScale);
1929
1930 Number x{100};
1931 Number const y = +x;
1932 EXPECT_EQ((x), (y));
1933 EXPECT_EQ((x++), (y));
1934 EXPECT_EQ((x), (Number{101}));
1935 EXPECT_EQ((x--), (Number{101}));
1936 EXPECT_EQ((x), (y));
1937 }
1938}
1939
1940TEST(NumberTest, to_st_amount)
1941{
1942 for (auto const mantissaScale : MantissaRange::getAllScales())
1943 {
1944 NumberMantissaScaleGuard const sg(mantissaScale);
1945
1946 Issue const issue;
1947 Number const n{7'518'783'80596, -5};
1949 auto res2 = STAmount{issue, n};
1950 EXPECT_EQ((res2), (STAmount{7518784}));
1951
1953 res2 = STAmount{issue, n};
1954 EXPECT_EQ((res2), (STAmount{7518783}));
1955
1957 res2 = STAmount{issue, n};
1958 EXPECT_EQ((res2), (STAmount{7518783}));
1959
1961 res2 = STAmount{issue, n};
1962 EXPECT_EQ((res2), (STAmount{7518784}));
1963 }
1964}
1965
1966TEST(NumberTest, truncate)
1967{
1968 for (auto const mantissaScale : MantissaRange::getAllScales())
1969 {
1970 NumberMantissaScaleGuard const sg(mantissaScale);
1971
1972 EXPECT_EQ((Number(25, +1).truncate()), (Number(250, 0)));
1973 EXPECT_EQ((Number(25, 0).truncate()), (Number(25, 0)));
1974 EXPECT_EQ((Number(25, -1).truncate()), (Number(2, 0)));
1975 EXPECT_EQ((Number(25, -2).truncate()), (Number(0, 0)));
1976 EXPECT_EQ((Number(99, -2).truncate()), (Number(0, 0)));
1977
1978 EXPECT_EQ((Number(-25, +1).truncate()), (Number(-250, 0)));
1979 EXPECT_EQ((Number(-25, 0).truncate()), (Number(-25, 0)));
1980 EXPECT_EQ((Number(-25, -1).truncate()), (Number(-2, 0)));
1981 EXPECT_EQ((Number(-25, -2).truncate()), (Number(0, 0)));
1982 EXPECT_EQ((Number(-99, -2).truncate()), (Number(0, 0)));
1983
1984 EXPECT_EQ((Number(0, 0).truncate()), (Number(0, 0)));
1985 EXPECT_EQ((Number(0, 30000).truncate()), (Number(0, 0)));
1986 EXPECT_EQ((Number(0, -30000).truncate()), (Number(0, 0)));
1987 EXPECT_EQ((Number(100, -30000).truncate()), (Number(0, 0)));
1988 EXPECT_EQ((Number(100, -30000).truncate()), (Number(0, 0)));
1989 EXPECT_EQ((Number(-100, -30000).truncate()), (Number(0, 0)));
1990 EXPECT_EQ((Number(-100, -30000).truncate()), (Number(0, 0)));
1991 }
1992}
1993
1994TEST(NumberTest, rounding)
1995{
1996 for (auto const mantissaScale : MantissaRange::getAllScales())
1997 {
1998 NumberMantissaScaleGuard const sg(mantissaScale);
1999
2000 // Test that rounding works as expected.
2001
2002 using NumberRoundings = std::map<Number::RoundingMode, std::int64_t>;
2003
2004 std::map<Number, NumberRoundings> const expected{
2005 // Positive numbers
2006 {Number{13, -1},
2011 {Number{23, -1},
2016 {Number{15, -1},
2021 {Number{25, -1},
2026 {Number{152, -2},
2031 {Number{252, -2},
2036 {Number{17, -1},
2041 {Number{27, -1},
2046
2047 // Negative numbers
2048 {Number{-13, -1},
2053 {Number{-23, -1},
2058 {Number{-15, -1},
2063 {Number{-25, -1},
2068 {Number{-152, -2},
2073 {Number{-252, -2},
2078 {Number{-17, -1},
2083 {Number{-27, -1},
2088 };
2089
2090 for (auto const& [num, roundings] : expected)
2091 {
2092 for (auto const& [mode, val] : roundings)
2093 {
2094 NumberRoundModeGuard const g{mode};
2095 auto const res = static_cast<std::int64_t>(num);
2096 EXPECT_EQ((res), (val)) << to_string(num) + " with mode " +
2097 std::to_string(static_cast<int>(mode)) + " expected " +
2098 std::to_string(val) + " got " + std::to_string(res);
2099 }
2100 }
2101 }
2102}
2103
2104TEST(NumberTest, int64)
2105{
2106 for (auto const mantissaScale : MantissaRange::getAllScales())
2107 {
2108 NumberMantissaScaleGuard const sg(mantissaScale);
2109
2110 auto const scale = Number::getMantissaScale();
2111
2112 // Control case
2113 EXPECT_GT((Number::maxMantissa()), (10));
2114 Number const ten{10};
2115 EXPECT_LE((ten.exponent()), (0));
2116
2118 {
2119 EXPECT_GT((std::numeric_limits<std::int64_t>::max()), (kInitialXrp.drops()));
2120 EXPECT_LT((Number::maxMantissa()), (kInitialXrp.drops()));
2121 Number const initalXrp{kInitialXrp};
2122 EXPECT_GT((initalXrp.exponent()), (0));
2123
2124 Number const maxInt64{Number::kMaxRep};
2125 EXPECT_GT((maxInt64.exponent()), (0));
2126 // 85'070'591'730'234'615'865'843'651'857'942'052'864 - 38 digits
2127 EXPECT_EQ((power(maxInt64, 2)), (Number{85'070'591'730'234'62, 22}));
2128
2129 Number const max = Number{false, Number::maxMantissa(), 0, Number::Normalized{}};
2130 EXPECT_LE(max.exponent(), 0);
2131 // 99'999'999'999'999'980'000'000'000'000'001 - 32 digits
2132 EXPECT_EQ(power(max, 2), (Number{99'999'999'999'999'98, 16}));
2133 }
2134 else
2135 {
2136 EXPECT_GT((std::numeric_limits<std::int64_t>::max()), (kInitialXrp.drops()));
2137 EXPECT_GT((Number::maxMantissa()), (kInitialXrp.drops()));
2138 Number const initalXrp{kInitialXrp};
2139 EXPECT_LE((initalXrp.exponent()), (0));
2140
2141 Number const maxInt64{Number::kMaxRep};
2142 EXPECT_LE((maxInt64.exponent()), (0));
2143 // 85'070'591'730'234'615'847'396'907'784'232'501'249 - 38 digits
2144 EXPECT_EQ((power(maxInt64, 2)), (Number{85'070'591'730'234'615'85, 19}));
2145
2147
2148 auto const maxMantissa = Number::maxMantissa();
2149 Number const max = Number{false, maxMantissa, 0, Number::Normalized{}};
2150 EXPECT_EQ((max.mantissa()), (maxMantissa / 10));
2151 EXPECT_EQ((max.exponent()), (1));
2152 // 99'999'999'999'999'999'800'000'000'000'000'000'100 - also 38
2153 // digits
2154 EXPECT_EQ(
2155 (power(max, 2)), (Number{false, (maxMantissa / 10) - 1, 20, Number::Normalized{}}));
2156 }
2157 }
2158}
2159
2160TEST(NumberTest, upward_rounding_produces_value_not_below_exact_at_k_max_rep_cusp)
2161{
2162 for (auto const mantissaScale : MantissaRange::getAllScales())
2163 {
2164 NumberMantissaScaleGuard const mg{mantissaScale};
2166
2167 auto const scale = Number::getMantissaScale();
2168
2169 constexpr std::int64_t kAValue = 1'000'000'000'000'049'863LL;
2170 constexpr std::int64_t kBValue = 9'223'372'036'854'315'903LL;
2171
2172 Number const a = kAValue;
2173 Number const b = kBValue;
2174 Number const product = a * b;
2175
2176 // Exact reference in BigInt.
2177 BigInt const exactProduct = BigInt(kAValue) * BigInt(kBValue);
2178
2179 // What Number actually stored.
2180 BigInt const storedValue = toBigInt(product);
2181
2182 BigInt const signedDifference = storedValue - exactProduct;
2183
2184 auto const message = [&] {
2186 os << " a = " << fmt(BigInt(kAValue)) << "\n"
2187 << " b = " << fmt(BigInt(kBValue)) << "\n"
2188 << " exact a*b = " << fmt(exactProduct) << "\n"
2189 << " stored = " << fmt(storedValue) << "\n"
2190 << " stored - exact = " << fmt(signedDifference) << "\n"
2191 << " upward = " << (signedDifference >= 0 ? "held" : "VIOLATED") << "\n"
2192 << " stored.mantissa = " << product.mantissa() << "\n"
2193 << " stored.exponent = " << product.exponent() << "\n\n";
2194 return os.str();
2195 };
2196
2197 switch (scale)
2198 {
2201 EXPECT_TRUE(signedDifference >= 0) << message();
2202 EXPECT_TRUE(signedDifference < pow10<BigInt>(product.exponent())) << message();
2203 EXPECT_EQ(product.mantissa(), (std::numeric_limits<std::int64_t>::max() / 10) + 1);
2204 EXPECT_EQ(product.exponent(), 19);
2205 break;
2206
2208 EXPECT_TRUE(signedDifference < 0) << message();
2209 EXPECT_EQ(
2210 product.mantissa(), (std::numeric_limits<std::int64_t>::max() / 100) * 100);
2211 EXPECT_EQ(product.exponent(), 18);
2212 break;
2213
2215 // The seemingly weird rounding here is because a & b are both
2216 // normalized, and both round up when being converted to Number,
2217 // so you're really getting
2218 // 1_000_000_000_000_050 * 9_223_372_036_854_316.
2219 EXPECT_TRUE(signedDifference >= 0) << message();
2220 EXPECT_EQ(
2221 product.mantissa(), (std::numeric_limits<std::int64_t>::max() / 1000) + 3);
2222 EXPECT_EQ(product.exponent(), 21);
2223 break;
2224 }
2225 }
2226}
2227
2228/*
2229 * Companion regression for the kMaxRep cusp behavior, but for `operator/=` on
2230 * the cusp-fix-ENABLED `Large` scale.
2231 *
2232 * Before the dropped-remainder fix, `operator/=` with Upward rounding could
2233 * return a value STRICTLY LESS than the exact quotient, violating Upward's
2234 * directional invariant.
2235 *
2236 * Mechanism (fix-enabled path):
2237 * 1. `operator/=` computes `numerator = nm * 10^17` and
2238 * `zm = numerator / dm` (integer division, truncates remainder).
2239 * 2. If `remainder != 0`, the correction block runs:
2240 * zm *= 100000
2241 * correction = (remainder * 100000) / dm // also truncates
2242 * zm += correction
2243 * ze -= 5
2244 * The truncation in `correction` discards a sub-1/100000 residual.
2245 * 3. `normalize`'s shift loop reduces zm to fit, but the discarded residual
2246 * is BELOW the Guard's visibility, so the Guard sees fraction = 0.
2247 * 4. Under Upward + positive, `round()` returns -1 (no round-up), and the
2248 * algorithm returns the truncated zm.
2249 */
2250TEST(NumberTest, upward_division_returns_value_not_below_exact_on_large_scale)
2251{
2252 for (auto const mantissaScale : MantissaRange::getAllScales())
2253 {
2254 NumberMantissaScaleGuard const mg{mantissaScale};
2256
2257 auto const scale = Number::getMantissaScale();
2258
2259 constexpr std::int64_t kAValue = 2LL;
2260 constexpr std::int64_t kBValue = 1'000'000'000'000'000'007LL;
2261 // kBValue = 10^18 + 7 (prime, in [minMantissa, kMaxRep]).
2262
2263 Number const a{kAValue, 0};
2264 Number const b{kBValue, 0};
2265 Number const quotient = a / b;
2266
2267 Dec const exact = Dec(kAValue) / Dec(kBValue);
2268 Dec const stored = Dec(quotient.mantissa()) * pow10(quotient.exponent());
2269 Dec const diff = stored - exact;
2270
2271 auto const message = [&] {
2273 os << " a = " << kAValue << "\n"
2274 << " b = " << kBValue << "\n"
2275 << " exact a/b = " << fmt(exact) << "\n"
2276 << " stored a/b = " << fmt(stored) << "\n"
2277 << " stored - exact = " << fmt(diff)
2278 << " (negative => Upward gave value BELOW truth)\n"
2279 << " quotient.mantissa = " << quotient.mantissa() << "\n"
2280 << " quotient.exponent = " << quotient.exponent() << "\n\n";
2281 return os.str();
2282 };
2283
2284 // Upward invariant: stored >= exact. Bug: stored < exact.
2285 switch (scale)
2286 {
2289 EXPECT_TRUE(stored >= exact) << message();
2290 EXPECT_TRUE(diff < pow10(quotient.exponent())) << message();
2291 break;
2292
2294 EXPECT_TRUE(stored < exact) << message();
2295 EXPECT_TRUE(diff >= -pow10(quotient.exponent())) << message();
2296 break;
2297
2299 // Small mantissa doesn't have the correction for dropped remainders.
2300 EXPECT_TRUE(stored < exact) << message();
2301 break;
2302 }
2303 }
2304}
2305
2306// Companion test case for Upward positive operator/=: Downward negative.
2307TEST(NumberTest, downward_division_returns_value_not_above_exact_on_large_scale)
2308{
2309 for (auto const mantissaScale : MantissaRange::getAllScales())
2310 {
2311 NumberMantissaScaleGuard const mg{mantissaScale};
2313
2314 auto const scale = Number::getMantissaScale();
2315
2316 constexpr std::int64_t kAValue = -2LL;
2317 constexpr std::int64_t kBValue = 1'000'000'000'000'000'007LL;
2318 // kBValue = 10^18 + 7 (prime, in [minMantissa, kMaxRep]).
2319
2320 Number const a{kAValue, 0};
2321 Number const b{kBValue, 0};
2322 Number const quotient = a / b;
2323
2324 Dec const exact = Dec(kAValue) / Dec(kBValue);
2325 Dec const stored = Dec(quotient.mantissa()) * pow10(quotient.exponent());
2326 Dec const diff = stored - exact;
2327
2328 auto const message = [&] {
2330 os << " a = " << kAValue << "\n"
2331 << " b = " << kBValue << "\n"
2332 << " exact a/b = " << fmt(exact) << "\n"
2333 << " stored a/b = " << fmt(stored) << "\n"
2334 << " stored - exact = " << fmt(diff)
2335 << " (positive => Downward gave value ABOVE truth)\n"
2336 << " quotient.mantissa = " << quotient.mantissa() << "\n"
2337 << " quotient.exponent = " << quotient.exponent() << "\n\n";
2338 return os.str();
2339 };
2340
2341 // invariant: stored <= exact. Bug: stored > exact.
2342 switch (scale)
2343 {
2346 EXPECT_TRUE(stored <= exact) << message();
2347 EXPECT_TRUE(diff > -pow10(quotient.exponent())) << message();
2348 break;
2349
2351 EXPECT_TRUE(stored > exact) << message();
2352 EXPECT_TRUE(diff <= pow10(quotient.exponent())) << message();
2353 break;
2354
2356 // Small mantissa doesn't have the correction for dropped remainders.
2357 EXPECT_TRUE(stored < exact) << message();
2358 break;
2359 }
2360 }
2361}
2362
2363/*
2364 * Companion test case for Upward positive operator/=: ToNearest.
2365 *
2366 * With ToNearest, if the dropped digits are exactly "5", then the mantissa will
2367 * be rounded to even. The numbers below result in a value where the unrounded
2368 * mantissa ends in an even digit, and "infinite precision" would drop
2369 * "500000000000000000145...", but doNormalize only sees "5". Without the
2370 * rounding fix, doNormalize rounds down to the even value. With the rounding
2371 * fix, doNormalize knows there are more digits beyond "5", and so rounds _up_
2372 * to the odd value.
2373 */
2374TEST(NumberTest, to_nearest_division_uses_dropped_digits_on_large_scale)
2375{
2376 for (auto const mantissaScale : MantissaRange::getAllScales())
2377 {
2378 NumberMantissaScaleGuard const mg{mantissaScale};
2380
2381 auto const scale = Number::getMantissaScale();
2382
2383 constexpr std::int64_t kAValue = 1'269'917'268'816'087'809LL;
2384 constexpr std::int64_t kBValue = 3'458'525'013'821'685'511LL;
2385 // kBValue is prime and in [minMantissa, kMaxRep].
2386
2387 Number const a{kAValue, 0};
2388 Number const b{kBValue, 0};
2389 Number const quotient = a / b;
2390
2391 Dec const exact = Dec(kAValue) / Dec(kBValue);
2392 Dec const stored = Dec(quotient.mantissa()) * pow10(quotient.exponent());
2393 Dec const diff = stored - exact;
2394
2395 auto const message = [&] {
2397 os << " a = " << kAValue << "\n"
2398 << " b = " << kBValue << "\n"
2399 << " exact a/b = " << fmt(exact) << "\n"
2400 << " stored a/b = " << fmt(stored) << "\n"
2401 << " stored - exact = " << fmt(diff)
2402 << " (negative => ToNearest gave value BELOW truth)\n"
2403 << " quotient.mantissa = " << quotient.mantissa() << "\n"
2404 << " quotient.exponent = " << quotient.exponent() << "\n\n";
2405 return os.str();
2406 };
2407
2408 // invariant: stored >= exact. Bug: stored < exact.
2409 switch (scale)
2410 {
2413 EXPECT_TRUE(stored >= exact) << message();
2414 EXPECT_TRUE(diff < pow10(quotient.exponent())) << message();
2415 break;
2416
2418 EXPECT_TRUE(stored < exact) << message();
2419 EXPECT_TRUE(diff >= -pow10(quotient.exponent())) << message();
2420 break;
2421
2423 // Small mantissa doesn't have the correction for dropped remainders.
2424 EXPECT_TRUE(stored < exact) << message();
2425 break;
2426 }
2427 }
2428}
2429
2430TEST(NumberTest, subtraction_rounding)
2431{
2432 for (auto const mantissaScale : MantissaRange::getAllScales())
2433 {
2434 NumberMantissaScaleGuard const mg{mantissaScale};
2436
2437 auto const scale = Number::getMantissaScale();
2438
2439 auto const exp = Number::mantissaLog();
2440 // SubCase is <offset, extraB, aString, bString>
2441 // * offset: offset from exp
2442 // * extraB: whether to include 1e"exp" in "b"
2443 // * aString: expected string value for "a"
2444 // * bString: expected string value for "b"
2445 // There aren't too many valid combinations for test cases here. If extraB is true,
2446 // offset can really only be 2, because any larger and the mantissa can't be represented
2447 // without loss. Offset can't be less than 2, or there's no error.
2449 auto const c = std::to_array<SubCase>({
2450 {2,
2451 true,
2452 scale == MantissaRange::MantissaScale::Small ? "100000000000000000"
2453 : "100000000000000000000",
2454 scale == MantissaRange::MantissaScale::Small ? "-1000000000000001"
2455 : "-1000000000000000001"},
2456 {2,
2457 false,
2458 scale == MantissaRange::MantissaScale::Small ? "100000000000000000"
2459 : "100000000000000000000",
2460 "-1"},
2461 {30,
2462 false,
2464 ? "1000000000000000000000000000000000000000000000"
2465 : "1000000000000000000000000000000000000000000000000",
2466 "-1"},
2467 });
2468
2469 for (auto const& [offset, extraB, aString, bString] : c)
2470 {
2471 Number const a{1LL, exp + offset};
2472 Number const b{-((extraB ? Number{1, exp} : kNumZero) + 1)};
2473
2474 auto const bigA = toBigInt(a);
2475 auto const bigB = toBigInt(b);
2476
2477 EXPECT_EQ(bigA, BigInt{aString});
2478 EXPECT_EQ(bigB, BigInt{bString});
2479
2480 auto construct = [&a, &b](Number::RoundingMode r) {
2481 NumberRoundModeGuard const roundGuard{r};
2482 auto const sum = a + b;
2483 BigInt const stored = toBigInt(sum);
2484 return std::make_pair(r, std::make_pair(stored, sum));
2485 };
2486
2487 BigInt const exact = bigA + bigB;
2488
2489 auto const sums = [&]() {
2495 return r;
2496 }();
2497
2498 auto const message = [&](auto const& r, auto const& sum) {
2500 os << " a = " << a << " (" << fmt(bigA) << ")\n b = " << b
2501 << " (" << fmt(bigB) << ")\n exact a + b = " << fmt(exact) << "\n";
2502
2503 auto const diff = sum.first - exact;
2504 auto const rLabel = to_string(r);
2505 os << std::string(15 - rLabel.length(), ' ') << rLabel << " = " << fmt(sum.first)
2506 << "\n difference = " << fmt(diff) << "\n\n";
2507
2508 return os.str();
2509 };
2510
2511 auto const expectedExponent =
2512 offset - (scale == MantissaRange::MantissaScale::Small && extraB ? 1 : 0);
2513 auto const epsilon = pow10<BigInt>(expectedExponent);
2514 for (auto const& [r, sum] : sums)
2515 {
2516 auto diff = sum.first - exact;
2517 switch (scale)
2518 {
2522 // Without the fix, all the results but one round up
2524 {
2525 // Downward works because the Guard sign is negative, and Downward
2526 // returns Up instead of Down if negative and there's a remainder,
2527 // whereas TowardsZero always returns Down.
2528 EXPECT_LT(sum.first, exact) << message(r, sum);
2529 EXPECT_EQ(diff, -(epsilon - 1)) << message(r, sum);
2530 }
2531 else
2532 {
2533 EXPECT_GT(sum.first, exact) << message(r, sum);
2534 EXPECT_EQ(diff, 1) << message(r, sum);
2535 }
2536 break;
2537 }
2538 default: {
2539 EXPECT_LE(sum.second.exponent(), expectedExponent) << message(r, sum);
2540 switch (r)
2541 {
2544 EXPECT_GT(sum.first, exact) << message(r, sum);
2545 EXPECT_EQ(diff, 1) << message(r, sum);
2546 break;
2547 default:
2548 EXPECT_LT(sum.first, exact) << message(r, sum);
2549 EXPECT_EQ(diff, -(epsilon - 1)) << message(r, sum);
2550 }
2551 }
2552 }
2553 }
2554 }
2555 }
2556}
2557
2558TEST(NumberTest, normalization_cusp_tonearest_and_downward)
2559{
2560 for (auto const mantissaScale : MantissaRange::getAllScales())
2561 {
2562 NumberMantissaScaleGuard const mg{mantissaScale};
2564
2565 auto const scale = Number::getMantissaScale();
2566
2567 constexpr auto kMaxRep = Number::kMaxRep;
2568
2569 // Both ToNearest and Downward should round to `below`
2570 auto constexpr actual = static_cast<std::uint64_t>(kMaxRep) + 1;
2571 Number const below{static_cast<std::int64_t>(kMaxRep), 0};
2572 Number const above{false, static_cast<std::uint64_t>(kMaxRep) + 3, 0, Number::Normalized{}};
2573
2574 auto construct = [](Number::RoundingMode mode) {
2575 NumberRoundModeGuard const roundGuard{mode};
2576 return Number(false, actual, 0, Number::Normalized{});
2577 };
2578 Number const upward = construct(Number::RoundingMode::Upward);
2579
2580 Number const toNearest = construct(Number::RoundingMode::ToNearest);
2581
2582 Number const downward = construct(Number::RoundingMode::Downward);
2583
2584 auto message = [&] {
2586 log << " actual = " << actual << " (kMaxRep + 1)\n"
2587 << " below = " << below << " (kMaxRep, distance 1)\n"
2588 << " above = " << above << " (kMaxRep + 3, distance 2)\n"
2589 << " Upward = " << upward << "\n"
2590 << " ToNearest = " << toNearest << "\n"
2591 << " Downward = " << downward << "\n\n";
2592 return log.str();
2593 };
2594
2595 switch (scale)
2596 {
2598 // With the small mantissa, everything but Downward rounds UP, including the
2599 // reference values, "above" and "below"
2600
2601 EXPECT_EQ(below, above) << message();
2602 EXPECT_EQ(upward, above) << message();
2603 EXPECT_EQ(toNearest, above) << message();
2604
2605 EXPECT_LT(downward, below) << message();
2606
2607 break;
2608
2611 // Upward round UP
2612 EXPECT_EQ(upward, above) << message();
2613
2614 // ToNearest rounds UP when the DOWN neighbor is strictly closer
2615 EXPECT_EQ(toNearest, above) << message();
2616 EXPECT_GT(toNearest, below) << message();
2617
2618 // Downward undershoots: it returns a value below `below`
2619 EXPECT_LT(downward, below) << message();
2620
2621 // Both should have given the same answer, but they differ
2622 EXPECT_GT(toNearest, downward) << message();
2623
2624 break;
2625 default:
2626 // Covers "Large" and any newly added scales
2627
2628 // Upward round UP
2629 EXPECT_EQ(upward, above) << message();
2630
2631 // ToNearest rounds to the strictly closer DOWN neighbor
2632 EXPECT_NE(toNearest, above) << message();
2633 EXPECT_EQ(toNearest, below) << message();
2634
2635 // Downward also rounds to `below`
2636 EXPECT_EQ(downward, below) << message();
2637
2638 // ToNearest rounds to downward
2639 EXPECT_EQ(toNearest, downward) << message();
2640 break;
2641 }
2642 }
2643}
2644
2645TEST(NumberTest, number_add_directed_sign_wrong)
2646{
2647 for (auto const mantissaScale : MantissaRange::getAllScales())
2648 {
2649 NumberMantissaScaleGuard const mg{mantissaScale};
2651
2652 auto const scale = Number::getMantissaScale();
2653 {
2654 // Two negative numbers with the same exponent
2655 Number const a{-6, Number::mantissaLog()};
2656 Number const b{a - 3};
2657 EXPECT_TRUE(a.exponent() == b.exponent() && abs(b) > abs(a));
2658
2659 BigInt const exact = toBigInt(a) + toBigInt(b);
2661 {
2662 EXPECT_EQ(exact, BigInt{"-12000000000000003"});
2663 }
2664 else
2665 {
2666 EXPECT_EQ(exact, BigInt{"-12000000000000000003"});
2667 }
2668
2669 Number down, up;
2670 {
2672 down = a + b;
2673 }
2674 {
2676 up = a + b;
2677 }
2678
2679 auto const valueDown = toBigInt(down);
2680 auto const valueUp = toBigInt(up);
2681 auto message = [&] {
2683 log << " exact = " << fmt(exact) << "\n downward = " << fmt(valueDown)
2684 << " (correct rounding: <= exact)"
2685 << "\n upward = " << fmt(valueUp) << " (correct rounding: >= exact)\n\n";
2686 return log.str();
2687 };
2688
2690 {
2691 EXPECT_LE(valueDown, exact) << message(); // Downward should round away from zero
2692 EXPECT_GE(valueUp, exact) << message(); // Upward should round toward 0
2693 }
2694 else
2695 {
2696 EXPECT_GT(valueDown, exact)
2697 << message(); // Downward rounded toward zero (too high)
2698 EXPECT_LT(valueUp, exact) << message(); // Upward rounded toward -inf (too low)
2699 }
2700 }
2701
2702 {
2703 // Positive control: the same magnitudes with a positive result round
2704 Number const pa{6, Number::mantissaLog()};
2705 Number const pb{pa + 3};
2706 EXPECT_TRUE(pa.exponent() == pb.exponent() && abs(pb) > abs(pa));
2707 BigInt const pexact = toBigInt(pa) + toBigInt(pb); // 12'000'000'000'000'000'003
2708
2709 Number pdown, pup;
2710 {
2712 pdown = pa + pb;
2713 }
2714 {
2716 pup = pa + pb;
2717 }
2718 auto const valuePDown = toBigInt(pdown);
2719 auto const valuePUp = toBigInt(pup);
2720 auto message = [&] {
2722 log << " exact = " << fmt(pexact) << "\n downward = " << fmt(valuePDown)
2723 << " (correct rounding: <= exact)"
2724 << "\n upward = " << fmt(valuePUp)
2725 << " (correct rounding: >= exact)\n\n";
2726 return log.str();
2727 };
2728
2729 EXPECT_LE(valuePDown, pexact) << message(); // correct for positive results
2730 EXPECT_GE(valuePUp, pexact) << message();
2731 }
2732
2733 {
2734 // Mixed sign numbers with the same exponent: negative second value
2735 Number const a{1, Number::mantissaLog()};
2736 Number const b{Number{-9, Number::mantissaLog()} - 3};
2737 EXPECT_TRUE(a.exponent() == b.exponent() && abs(b) > abs(a));
2738
2739 BigInt const exact = toBigInt(a) + toBigInt(b);
2741 {
2742 EXPECT_EQ(exact, BigInt{"-8000000000000003"});
2743 }
2744 else
2745 {
2746 EXPECT_EQ(exact, BigInt{"-8000000000000000003"});
2747 }
2748
2749 Number down, up;
2750 {
2752 down = a + b;
2753 }
2754 {
2756 up = a + b;
2757 }
2758
2759 auto const valueDown = toBigInt(down);
2760 auto const valueUp = toBigInt(up);
2761 auto message = [&] {
2763 log << " exact = " << fmt(exact) << "\n downward = " << fmt(valueDown)
2764 << " (correct rounding: <= exact)"
2765 << "\n upward = " << fmt(valueUp) << " (correct rounding: >= exact)\n\n";
2766 return log.str();
2767 };
2768
2769 EXPECT_LE(valueDown, exact) << message(); // Downward should round away from zero
2770 EXPECT_GE(valueUp, exact) << message(); // Upward should round toward 0
2771 }
2772
2773 {
2774 // Mixed sign numbers with the same exponent: negative first value
2775 Number const a{-1, Number::mantissaLog()};
2776 Number const b{Number{9, Number::mantissaLog()} + 3};
2777 EXPECT_TRUE(a.exponent() == b.exponent() && abs(b) > abs(a));
2778
2779 BigInt const exact = toBigInt(a) + toBigInt(b);
2781 {
2782 EXPECT_EQ(exact, BigInt{"8000000000000003"});
2783 }
2784 else
2785 {
2786 EXPECT_EQ(exact, BigInt{"8000000000000000003"});
2787 }
2788
2789 Number down, up;
2790 {
2792 down = a + b;
2793 }
2794 {
2796 up = a + b;
2797 }
2798
2799 auto const valueDown = toBigInt(down);
2800 auto const valueUp = toBigInt(up);
2801 auto message = [&] {
2803 log << " exact = " << fmt(exact) << "\n downward = " << fmt(valueDown)
2804 << " (correct rounding: <= exact)"
2805 << "\n upward = " << fmt(valueUp) << " (correct rounding: >= exact)\n\n";
2806 return log.str();
2807 };
2808
2809 EXPECT_LE(valueDown, exact) << message(); // Downward should round away from zero
2810 EXPECT_GE(valueUp, exact) << message(); // Upward should round toward 0
2811 }
2812 }
2813}
2814
2815TEST(NumberTest, number_add_to_nearest_picks_farther)
2816{
2817 for (auto const mantissaScale : MantissaRange::getAllScales())
2818 {
2819 NumberMantissaScaleGuard const mg{mantissaScale};
2821
2822 auto const scale = Number::getMantissaScale();
2823
2824 // Case is <y, expected q>
2826
2827 auto const c = std::to_array<Case>({
2828 {Number{5'175'909'259'972'499'745LL, 22}, -1'074'951'375'311'646'003},
2829 {Number{1}, -1'074'956'551'220'905'975},
2830 {Number{1, 10}, -1'074'956'551'220'905'975},
2831 {Number{1, 20}, -1'074'956'551'220'905'975},
2832 {Number{1, 27}, -1'074'956'551'220'905'975},
2833 {Number{1, 28}, -1'074'956'551'220'905'974},
2834 {Number{1, 31}, -1'074'956'551'220'904'975},
2835 });
2836
2837 for (auto const& [y, expectedQ] : c)
2838 {
2839 Number const x{-1'074'956'551'220'905'975LL, 28};
2840 Number const res = x + y;
2841
2842 BigInt const exact = toBigInt(x) + toBigInt(y);
2843 BigInt const vres = toBigInt(res);
2844
2845 BigInt ulp = 1;
2846 for (int i = 0; i < res.exponent(); ++i)
2847 ulp *= 10;
2848
2849 BigInt const q = (exact - ulp / 2) / ulp;
2850 Number const normalizedExact{static_cast<std::int64_t>(q), res.exponent()};
2851 BigInt const norm = toBigInt(normalizedExact);
2852
2853 auto message = [&](auto const& comp) {
2855 log << fmt(q) + " != " + fmt(comp) << "\n"
2856 << " x = " << x << "\n y = " << y
2857 << "\n exact = " << fmt(exact)
2858 << "\n result (x + y) = " << fmt(vres)
2859 << "\n normalize(exact) = " << fmt(norm) << "\n\n";
2860 return log.str();
2861 };
2862
2864 {
2865 auto const comp = toBigInt(Number{expectedQ, -3});
2866 EXPECT_EQ(q, comp) << message(comp);
2867 }
2868 else
2869 {
2870 EXPECT_EQ(q, expectedQ) << message(BigInt(expectedQ));
2871 }
2872 EXPECT_EQ(normalizedExact, res);
2873 }
2874 }
2875}
2876
2877TEST(NumberTest, number_cusp_rounding_with_fractional_parts)
2878{
2879 for (auto const mantissaScale : MantissaRange::getAllScales())
2880 {
2881 NumberMantissaScaleGuard const mg{mantissaScale};
2882
2883 auto const scale = Number::getMantissaScale();
2884
2885 Number const below{static_cast<std::int64_t>(Number::kMaxRep), 0};
2886 Number const above{false, Number::kMaxRepUp, 0, Number::Normalized{}};
2887
2888 auto header = [&] {
2890 log << "Scale: " << to_string(mantissaScale) << ", Below: " << below
2891 << ", Above: " << above << "\n";
2892 return log.str();
2893 };
2894
2895 auto const zeroPointFour = Number(4, -1);
2896 auto const zeroPointFive = Number(5, -1);
2897 auto const zeroPointSix = Number(6, -1);
2898 auto const onePointFour = Number(14, -1);
2899 auto const onePointFive = Number(15, -1);
2900 auto const onePointSix = Number(16, -1);
2901 auto const twoPointFour = Number(24, -1);
2902 auto const twoPointFive = Number(25, -1);
2903 auto const twoPointSix = Number(26, -1);
2904
2905 auto const operands = std::to_array<Number>({
2906 zeroPointFour,
2907 zeroPointFive,
2908 zeroPointSix,
2909 onePointFour,
2910 onePointFive,
2911 onePointSix,
2912 twoPointFour,
2913 twoPointFive,
2914 twoPointSix,
2915 });
2916
2917 auto const modes = std::to_array<Number::RoundingMode>({
2922 });
2923
2924 // Addition cases test kMaxRep + Operand
2925 for (auto const& mode : modes)
2926 {
2927 for (auto const& operand : operands)
2928 {
2929 NumberRoundModeGuard const rg{mode};
2930
2931 auto const expectedValue = [&]() {
2932 // Returns "above" by default. The checks here are for exceptions.
2934 {
2935 if (mode == Number::RoundingMode::ToNearest && operand < onePointFive)
2936 return below;
2939 return below;
2940 }
2942 {
2944 {
2945 if (operand < zeroPointFive)
2946 return below;
2947 }
2950 {
2951 if (operand >= onePointFour)
2952 return below - 7;
2953 return below;
2954 }
2955 }
2957 {
2959 {
2960 if (operand < zeroPointFive)
2961 return below;
2962 if (operand <= zeroPointSix)
2963 return below - 7;
2964 }
2967 {
2968 if (operand >= onePointFour)
2969 return below - 7;
2970 return below;
2971 }
2972 if (mode == Number::RoundingMode::Upward && operand <= zeroPointSix)
2973 return below - 7;
2974 }
2977 return above + 1000;
2978 return above;
2979 }();
2980
2981 Number const actual = below + operand;
2982
2983 auto message = [&] {
2985 ss << header() << "kMaxRep + " << operand << " rounded " << to_string(mode)
2986 << " to " << actual << ". Expected: " << expectedValue;
2987 return ss.str();
2988 };
2989 EXPECT_EQ(actual, expectedValue) << message();
2990 }
2991 }
2992
2993 // Subtraction cases test kMaxRepUp - Operand
2994 for (auto const& mode : modes)
2995 {
2996 for (auto const& operand : operands)
2997 {
2998 NumberRoundModeGuard const rg{mode};
2999
3000 auto const expectedValue = [&]() {
3002 {
3003 if (mode == Number::RoundingMode::ToNearest && operand > onePointFive)
3004 return below;
3007 return below;
3008 }
3011 {
3013 {
3014 if (operand >= twoPointSix)
3015 return below;
3016 }
3018 {
3019 if (operand >= onePointFour)
3020 return below - 7;
3021 }
3023 {
3024 if (operand <= onePointSix)
3025 return below - 7;
3026 return below;
3027 }
3028 }
3030 {
3032 return below - 1000;
3033 if (mode == Number::RoundingMode::Upward)
3034 return below;
3035 }
3036 return above;
3037 }();
3038
3039 Number const actual = above - operand;
3040
3041 auto message = [&] {
3043 ss << header() << "kMaxRepUp - " << operand << " rounded " << to_string(mode)
3044 << " to " << actual << ". Expected: " << expectedValue;
3045 return ss.str();
3046 };
3047 EXPECT_EQ(actual, expectedValue) << message();
3048 }
3049 }
3050 }
3051}
3052
3053} // namespace xrpl
T begin(T... args)
Floating point representation of amounts with high dynamic range.
Definition IOUAmount.h:26
A currency issued by an account.
Definition Issue.h:18
Sets the new scale and restores the old scale when it leaves scope.
Definition Number.h:963
Number is a floating point type that can represent a wide range of values.
Definition Number.h:351
constexpr rep mantissa() const noexcept
Returns the mantissa of the external view of the Number.
Definition Number.h:692
static InternalRep maxMantissa()
Definition Number.h:568
static constexpr InternalRep kMaxRepUp
Definition Number.h:367
static constexpr int kMinExponent
Definition Number.h:361
static RoundingMode setround(RoundingMode inMode)
static constexpr InternalRep kMaxRep
Definition Number.h:364
static Number max() noexcept
Definition Number.h:819
static RoundingMode getround()
static MantissaRange::MantissaScale getMantissaScale()
Returns which mantissa scale is currently in use for normalization.
static InternalRep minMantissa()
Definition Number.h:562
static constexpr int kMaxExponent
Definition Number.h:362
constexpr int exponent() const noexcept
Returns the exponent of the external view of the Number.
Definition Number.h:714
static Number min() noexcept
Definition Number.h:813
static Number lowest() noexcept
Definition Number.h:825
static int mantissaLog()
Definition Number.h:574
T emplace_back(T... args)
T emplace(T... args)
T insert(T... args)
T invoke(T... args)
T is_sorted(T... args)
T make_pair(T... args)
T max(T... args)
T min(T... args)
constexpr Zero kZero
Definition Zero.h:30
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
static constexpr Number kNumZero
Definition Number.h:663
static auto sum(TCollection const &col)
TEST(FileUtilitiesTest, get_file_contents)
boost::multiprecision::cpp_dec_float_50 Dec
int scale(Number const &number, Asset const &asset)
Get the scale of a Number for a given asset.
Definition STAmount.h:794
Number root(Number f, unsigned d)
boost::multiprecision::cpp_int BigInt
Number power(Number const &f, unsigned n)
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:657
static std::string fmt(BigInt const &value)
Number root2(Number f)
constexpr Number abs(Number x) noexcept
Definition Number.h:876
BigInt toBigInt(Number const &n)
constexpr Number squelch(Number const &x, Number const &limit) noexcept
Definition Number.h:907
static T pow10(int n)
constexpr XRPAmount kInitialXrp
Configure the native currency.
T reserve(T... args)
T setprecision(T... args)
T str(T... args)
static std::set< MantissaScale > const & getAllScales()
Definition Number.h:178
T to_string(T... args)
T what(T... args)