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