rippled
Loading...
Searching...
No Matches
Number_test.cpp
1#include <xrpl/basics/Number.h>
2#include <xrpl/beast/unit_test.h>
3#include <xrpl/protocol/IOUAmount.h>
4#include <xrpl/protocol/STAmount.h>
5#include <xrpl/protocol/SystemParameters.h>
6
7#include <sstream>
8#include <tuple>
9
10namespace xrpl {
11
13{
14public:
15 void
17 {
19
20 for (Number const& z : {Number{0, 0}, Number{0}})
21 {
22 BEAST_EXPECT(z.mantissa() == 0);
23 BEAST_EXPECT(z.exponent() == Number{}.exponent());
24
25 BEAST_EXPECT((z + z) == z);
26 BEAST_EXPECT((z - z) == z);
27 BEAST_EXPECT(z == -z);
28 }
29 }
30
31 void
33 {
34 auto const scale = Number::getMantissaScale();
35 testcase << "test_limits " << to_string(scale);
36 bool caught = false;
37 auto const minMantissa = Number::minMantissa();
38 try
39 {
40 Number x =
41 Number{false, minMantissa * 10, 32768, Number::normalized{}};
42 }
43 catch (std::overflow_error const&)
44 {
45 caught = true;
46 }
47 BEAST_EXPECT(caught);
48
49 auto test = [this](auto const& x, auto const& y, int line) {
50 auto const result = x == y;
52 ss << x << " == " << y << " -> " << (result ? "true" : "false");
53 expect(result, ss.str(), __FILE__, line);
54 };
55
56 test(
57 Number{false, minMantissa * 10, 32767, Number::normalized{}},
58 Number{false, minMantissa, 32768, Number::normalized{}},
59 __LINE__);
60 test(
61 Number{false, minMantissa, -32769, Number::normalized{}},
62 Number{},
63 __LINE__);
64 test(
65 Number{false, minMantissa, 32000, Number::normalized{}} * 1'000 +
66 Number{false, 1'500, 32000, Number::normalized{}},
67 Number{false, minMantissa + 2, 32003, Number::normalized{}},
68 __LINE__);
69 // 9,223,372,036,854,775,808
70
71 test(
74 ? Number{-9'223'372'036'854'776, 3}
75 : Number{true, 9'223'372'036'854'775'808ULL, 0, Number::normalized{}},
76 __LINE__);
77 test(
79 scale == MantissaRange::small ? Number{-9'223'372'036'854'776, 3}
80 : Number{-9'223'372'036'854'775'807},
81 __LINE__);
82 test(
84 Number{
86 ? 9'223'372'036'854'776
88 18 - Number::mantissaLog()},
89 __LINE__);
90 caught = false;
91 try
92 {
93 [[maybe_unused]]
94 Number q =
95 Number{false, minMantissa, 32767, Number::normalized{}} * 100;
96 }
97 catch (std::overflow_error const&)
98 {
99 caught = true;
100 }
101 BEAST_EXPECT(caught);
102 }
103
104 void
106 {
107 auto const scale = Number::getMantissaScale();
108 testcase << "test_add " << to_string(scale);
109
111 auto const cSmall = std::to_array<Case>(
112 {{Number{1'000'000'000'000'000, -15},
113 Number{6'555'555'555'555'555, -29},
114 Number{1'000'000'000'000'066, -15}},
115 {Number{-1'000'000'000'000'000, -15},
116 Number{-6'555'555'555'555'555, -29},
117 Number{-1'000'000'000'000'066, -15}},
118 {Number{-1'000'000'000'000'000, -15},
119 Number{6'555'555'555'555'555, -29},
120 Number{-9'999'999'999'999'344, -16}},
121 {Number{-6'555'555'555'555'555, -29},
122 Number{1'000'000'000'000'000, -15},
123 Number{9'999'999'999'999'344, -16}},
124 {Number{}, Number{5}, Number{5}},
125 {Number{5}, Number{}, Number{5}},
126 {Number{5'555'555'555'555'555, -32768},
127 Number{-5'555'555'555'555'554, -32768},
128 Number{0}},
129 {Number{-9'999'999'999'999'999, -31},
130 Number{1'000'000'000'000'000, -15},
131 Number{9'999'999'999'999'990, -16}}});
132 auto const cLarge = std::to_array<Case>(
133 // Note that items with extremely large mantissas need to be
134 // calculated, because otherwise they overflow uint64. Items from C
135 // with larger mantissa
136 {
137 {Number{1'000'000'000'000'000, -15},
138 Number{6'555'555'555'555'555, -29},
139 Number{1'000'000'000'000'065'556, -18}},
140 {Number{-1'000'000'000'000'000, -15},
141 Number{-6'555'555'555'555'555, -29},
142 Number{-1'000'000'000'000'065'556, -18}},
143 {Number{-1'000'000'000'000'000, -15},
144 Number{6'555'555'555'555'555, -29},
145 Number{
146 true,
147 9'999'999'999'999'344'444ULL,
148 -19,
150 {Number{-6'555'555'555'555'555, -29},
151 Number{1'000'000'000'000'000, -15},
152 Number{
153 false,
154 9'999'999'999'999'344'444ULL,
155 -19,
157 {Number{}, Number{5}, Number{5}},
158 {Number{5}, Number{}, Number{5}},
159 {Number{5'555'555'555'555'555'000, -32768},
160 Number{-5'555'555'555'555'554'000, -32768},
161 Number{0}},
162 {Number{-9'999'999'999'999'999, -31},
163 Number{1'000'000'000'000'000, -15},
164 Number{9'999'999'999'999'990, -16}},
165 // Items from cSmall expanded for the larger mantissa
166 {Number{1'000'000'000'000'000'000, -18},
167 Number{6'555'555'555'555'555'555, -35},
168 Number{1'000'000'000'000'000'066, -18}},
169 {Number{-1'000'000'000'000'000'000, -18},
170 Number{-6'555'555'555'555'555'555, -35},
171 Number{-1'000'000'000'000'000'066, -18}},
172 {Number{-1'000'000'000'000'000'000, -18},
173 Number{6'555'555'555'555'555'555, -35},
174 Number{
175 true,
176 9'999'999'999'999'999'344ULL,
177 -19,
179 {Number{-6'555'555'555'555'555'555, -35},
180 Number{1'000'000'000'000'000'000, -18},
181 Number{
182 false,
183 9'999'999'999'999'999'344ULL,
184 -19,
186 {Number{}, Number{5}, Number{5}},
187 {Number{5'555'555'555'555'555'555, -32768},
188 Number{-5'555'555'555'555'555'554, -32768},
189 Number{0}},
190 {Number{
191 true,
192 9'999'999'999'999'999'999ULL,
193 -37,
195 Number{1'000'000'000'000'000'000, -18},
196 Number{
197 false,
198 9'999'999'999'999'999'990ULL,
199 -19,
202 Number{6, -1},
203 Number{Number::maxRep / 10, 1}},
205 Number{1, 0},
207 // Test extremes
208 {
209 // Each Number operand rounds up, so the actual mantissa is
210 // minMantissa
211 Number{
212 false,
213 9'999'999'999'999'999'999ULL,
214 0,
216 Number{
217 false,
218 9'999'999'999'999'999'999ULL,
219 0,
221 Number{2, 19},
222 },
223 {
224 // Does not round. Mantissas are going to be > maxRep, so if
225 // added together as uint64_t's, the result will overflow.
226 // With addition using uint128_t, there's no problem. After
227 // normalizing, the resulting mantissa ends up less than
228 // maxRep.
229 Number{
230 false,
231 9'999'999'999'999'999'990ULL,
232 0,
234 Number{
235 false,
236 9'999'999'999'999'999'990ULL,
237 0,
239 Number{
240 false,
241 1'999'999'999'999'999'998ULL,
242 1,
244 },
245 });
246 auto test = [this](auto const& c) {
247 for (auto const& [x, y, z] : c)
248 {
249 auto const result = x + y;
251 ss << x << " + " << y << " = " << result << ". Expected: " << z;
252 BEAST_EXPECTS(result == z, ss.str());
253 }
254 };
255 if (scale == MantissaRange::small)
256 test(cSmall);
257 else
258 test(cLarge);
259 {
260 bool caught = false;
261 try
262 {
263 Number{
264 false, Number::maxMantissa(), 32768, Number::normalized{}} +
265 Number{
266 false,
268 32767,
270 5;
271 }
272 catch (std::overflow_error const&)
273 {
274 caught = true;
275 }
276 BEAST_EXPECT(caught);
277 }
278 }
279
280 void
282 {
283 auto const scale = Number::getMantissaScale();
284 testcase << "test_sub " << to_string(scale);
285
287 auto const cSmall = std::to_array<Case>(
288 {{Number{1'000'000'000'000'000, -15},
289 Number{6'555'555'555'555'555, -29},
290 Number{9'999'999'999'999'344, -16}},
291 {Number{6'555'555'555'555'555, -29},
292 Number{1'000'000'000'000'000, -15},
293 Number{-9'999'999'999'999'344, -16}},
294 {Number{1'000'000'000'000'000, -15},
295 Number{1'000'000'000'000'000, -15},
296 Number{0}},
297 {Number{1'000'000'000'000'000, -15},
298 Number{1'000'000'000'000'001, -15},
299 Number{-1'000'000'000'000'000, -30}},
300 {Number{1'000'000'000'000'001, -15},
301 Number{1'000'000'000'000'000, -15},
302 Number{1'000'000'000'000'000, -30}}});
303 auto const cLarge = std::to_array<Case>(
304 // Note that items with extremely large mantissas need to be
305 // calculated, because otherwise they overflow uint64. Items from C
306 // with larger mantissa
307 {
308 {Number{1'000'000'000'000'000, -15},
309 Number{6'555'555'555'555'555, -29},
310 Number{
311 false,
312 9'999'999'999'999'344'444ULL,
313 -19,
315 {Number{6'555'555'555'555'555, -29},
316 Number{1'000'000'000'000'000, -15},
317 Number{
318 true,
319 9'999'999'999'999'344'444ULL,
320 -19,
322 {Number{1'000'000'000'000'000, -15},
323 Number{1'000'000'000'000'000, -15},
324 Number{0}},
325 {Number{1'000'000'000'000'000, -15},
326 Number{1'000'000'000'000'001, -15},
327 Number{-1'000'000'000'000'000, -30}},
328 {Number{1'000'000'000'000'001, -15},
329 Number{1'000'000'000'000'000, -15},
330 Number{1'000'000'000'000'000, -30}},
331 // Items from cSmall expanded for the larger mantissa
332 {Number{1'000'000'000'000'000'000, -18},
333 Number{6'555'555'555'555'555'555, -32},
334 Number{
335 false,
336 9'999'999'999'999'344'444ULL,
337 -19,
339 {Number{6'555'555'555'555'555'555, -32},
340 Number{1'000'000'000'000'000'000, -18},
341 Number{
342 true,
343 9'999'999'999'999'344'444ULL,
344 -19,
346 {Number{1'000'000'000'000'000'000, -18},
347 Number{1'000'000'000'000'000'000, -18},
348 Number{0}},
349 {Number{1'000'000'000'000'000'000, -18},
350 Number{1'000'000'000'000'000'001, -18},
351 Number{-1'000'000'000'000'000'000, -36}},
352 {Number{1'000'000'000'000'000'001, -18},
353 Number{1'000'000'000'000'000'000, -18},
354 Number{1'000'000'000'000'000'000, -36}},
356 Number{6, -1},
358 {Number{false, Number::maxRep + 1, 0, Number::normalized{}},
359 Number{1, 0},
360 Number{Number::maxRep / 10 + 1, 1}},
361 {Number{false, Number::maxRep + 1, 0, Number::normalized{}},
362 Number{3, 0},
364 {power(2, 63), Number{3, 0}, Number{Number::maxRep}},
365 });
366 auto test = [this](auto const& c) {
367 for (auto const& [x, y, z] : c)
368 {
369 auto const result = x - y;
371 ss << x << " - " << y << " = " << result << ". Expected: " << z;
372 BEAST_EXPECTS(result == z, ss.str());
373 }
374 };
375 if (scale == MantissaRange::small)
376 test(cSmall);
377 else
378 test(cLarge);
379 }
380
381 void
383 {
384 auto const scale = Number::getMantissaScale();
385 testcase << "test_mul " << to_string(scale);
386
388 auto test = [this](auto const& c) {
389 for (auto const& [x, y, z] : c)
390 {
391 auto const result = x * y;
393 ss << x << " * " << y << " = " << result << ". Expected: " << z;
394 BEAST_EXPECTS(result == z, ss.str());
395 }
396 };
397 auto tests = [&](auto const& cSmall, auto const& cLarge) {
398 if (scale == MantissaRange::small)
399 test(cSmall);
400 else
401 test(cLarge);
402 };
403 auto const maxMantissa = Number::maxMantissa();
404
406 {
407 auto const cSmall = std::to_array<Case>({
408 {Number{7}, Number{8}, Number{56}},
409 {Number{1414213562373095, -15},
410 Number{1414213562373095, -15},
411 Number{2000000000000000, -15}},
412 {Number{-1414213562373095, -15},
413 Number{1414213562373095, -15},
414 Number{-2000000000000000, -15}},
415 {Number{-1414213562373095, -15},
416 Number{-1414213562373095, -15},
417 Number{2000000000000000, -15}},
418 {Number{3214285714285706, -15},
419 Number{3111111111111119, -15},
420 Number{1000000000000000, -14}},
421 {Number{1000000000000000, -32768},
422 Number{1000000000000000, -32768},
423 Number{0}},
424 // Maximum mantissa range
425 {Number{9'999'999'999'999'999, 0},
426 Number{9'999'999'999'999'999, 0},
427 Number{9'999'999'999'999'998, 16}},
428 });
429 auto const cLarge = std::to_array<Case>({
430 // Note that items with extremely large mantissas need to be
431 // calculated, because otherwise they overflow uint64. Items
432 // from C with larger mantissa
433 {Number{7}, Number{8}, Number{56}},
434 {Number{1414213562373095, -15},
435 Number{1414213562373095, -15},
436 Number{1999999999999999862, -18}},
437 {Number{-1414213562373095, -15},
438 Number{1414213562373095, -15},
439 Number{-1999999999999999862, -18}},
440 {Number{-1414213562373095, -15},
441 Number{-1414213562373095, -15},
442 Number{1999999999999999862, -18}},
443 {Number{3214285714285706, -15},
444 Number{3111111111111119, -15},
445 Number{
446 false,
447 9'999'999'999'999'999'579ULL,
448 -18,
450 {Number{1000000000000000000, -32768},
451 Number{1000000000000000000, -32768},
452 Number{0}},
453 // Items from cSmall expanded for the larger mantissa,
454 // except duplicates. Sadly, it looks like sqrt(2)^2 != 2
455 // with higher precision
456 {Number{1414213562373095049, -18},
457 Number{1414213562373095049, -18},
458 Number{2000000000000000001, -18}},
459 {Number{-1414213562373095048, -18},
460 Number{1414213562373095048, -18},
461 Number{-1999999999999999998, -18}},
462 {Number{-1414213562373095048, -18},
463 Number{-1414213562373095049, -18},
464 Number{1999999999999999999, -18}},
465 {Number{3214285714285714278, -18},
466 Number{3111111111111111119, -18},
467 Number{10, 0}},
468 // Maximum mantissa range - rounds up to 1e19
471 Number{1, 38}},
472 // Maximum int64 range
475 Number{85'070'591'730'234'615'85, 19}},
476 });
477 tests(cSmall, cLarge);
478 }
480 testcase << "test_mul " << to_string(Number::getMantissaScale())
481 << " towards_zero";
482 {
483 auto const cSmall = std::to_array<Case>(
484 {{Number{7}, Number{8}, Number{56}},
485 {Number{1414213562373095, -15},
486 Number{1414213562373095, -15},
487 Number{1999999999999999, -15}},
488 {Number{-1414213562373095, -15},
489 Number{1414213562373095, -15},
490 Number{-1999999999999999, -15}},
491 {Number{-1414213562373095, -15},
492 Number{-1414213562373095, -15},
493 Number{1999999999999999, -15}},
494 {Number{3214285714285706, -15},
495 Number{3111111111111119, -15},
496 Number{9999999999999999, -15}},
497 {Number{1000000000000000, -32768},
498 Number{1000000000000000, -32768},
499 Number{0}}});
500 auto const cLarge = std::to_array<Case>(
501 // Note that items with extremely large mantissas need to be
502 // calculated, because otherwise they overflow uint64. Items
503 // from C with larger mantissa
504 {
505 {Number{7}, Number{8}, Number{56}},
506 {Number{1414213562373095, -15},
507 Number{1414213562373095, -15},
508 Number{1999999999999999861, -18}},
509 {Number{-1414213562373095, -15},
510 Number{1414213562373095, -15},
511 Number{-1999999999999999861, -18}},
512 {Number{-1414213562373095, -15},
513 Number{-1414213562373095, -15},
514 Number{1999999999999999861, -18}},
515 {Number{3214285714285706, -15},
516 Number{3111111111111119, -15},
517 Number{
518 false,
519 9999999999999999579ULL,
520 -18,
522 {Number{1000000000000000000, -32768},
523 Number{1000000000000000000, -32768},
524 Number{0}},
525 // Items from cSmall expanded for the larger mantissa,
526 // except duplicates. Sadly, it looks like sqrt(2)^2 != 2
527 // with higher precision
528 {Number{1414213562373095049, -18},
529 Number{1414213562373095049, -18},
530 Number{2, 0}},
531 {Number{-1414213562373095048, -18},
532 Number{1414213562373095048, -18},
533 Number{-1999999999999999997, -18}},
534 {Number{-1414213562373095048, -18},
535 Number{-1414213562373095049, -18},
536 Number{1999999999999999999, -18}},
537 {Number{3214285714285714278, -18},
538 Number{3111111111111111119, -18},
539 Number{10, 0}},
540 // Maximum mantissa range - rounds down to maxMantissa/10e1
541 // 99'999'999'999'999'999'800'000'000'000'000'000'100
544 Number{
545 false,
546 maxMantissa / 10 - 1,
547 20,
549 // Maximum int64 range
550 // 85'070'591'730'234'615'847'396'907'784'232'501'249
553 Number{85'070'591'730'234'615'84, 19}},
554 });
555 tests(cSmall, cLarge);
556 }
558 testcase << "test_mul " << to_string(Number::getMantissaScale())
559 << " downward";
560 {
561 auto const cSmall = std::to_array<Case>(
562 {{Number{7}, Number{8}, Number{56}},
563 {Number{1414213562373095, -15},
564 Number{1414213562373095, -15},
565 Number{1999999999999999, -15}},
566 {Number{-1414213562373095, -15},
567 Number{1414213562373095, -15},
568 Number{-2000000000000000, -15}},
569 {Number{-1414213562373095, -15},
570 Number{-1414213562373095, -15},
571 Number{1999999999999999, -15}},
572 {Number{3214285714285706, -15},
573 Number{3111111111111119, -15},
574 Number{9999999999999999, -15}},
575 {Number{1000000000000000, -32768},
576 Number{1000000000000000, -32768},
577 Number{0}}});
578 auto const cLarge = std::to_array<Case>(
579 // Note that items with extremely large mantissas need to be
580 // calculated, because otherwise they overflow uint64. Items
581 // from C with larger mantissa
582 {
583 {Number{7}, Number{8}, Number{56}},
584 {Number{1414213562373095, -15},
585 Number{1414213562373095, -15},
586 Number{1999999999999999861, -18}},
587 {Number{-1414213562373095, -15},
588 Number{1414213562373095, -15},
589 Number{-1999999999999999862, -18}},
590 {Number{-1414213562373095, -15},
591 Number{-1414213562373095, -15},
592 Number{1999999999999999861, -18}},
593 {Number{3214285714285706, -15},
594 Number{3111111111111119, -15},
595 Number{
596 false,
597 9'999'999'999'999'999'579ULL,
598 -18,
600 {Number{1000000000000000000, -32768},
601 Number{1000000000000000000, -32768},
602 Number{0}},
603 // Items from cSmall expanded for the larger mantissa,
604 // except duplicates. Sadly, it looks like sqrt(2)^2 != 2
605 // with higher precision
606 {Number{1414213562373095049, -18},
607 Number{1414213562373095049, -18},
608 Number{2, 0}},
609 {Number{-1414213562373095048, -18},
610 Number{1414213562373095048, -18},
611 Number{-1999999999999999998, -18}},
612 {Number{-1414213562373095048, -18},
613 Number{-1414213562373095049, -18},
614 Number{1999999999999999999, -18}},
615 {Number{3214285714285714278, -18},
616 Number{3111111111111111119, -18},
617 Number{10, 0}},
618 // Maximum mantissa range - rounds down to maxMantissa/10e1
619 // 99'999'999'999'999'999'800'000'000'000'000'000'100
622 Number{
623 false,
624 maxMantissa / 10 - 1,
625 20,
627 // Maximum int64 range
628 // 85'070'591'730'234'615'847'396'907'784'232'501'249
631 Number{85'070'591'730'234'615'84, 19}},
632 });
633 tests(cSmall, cLarge);
634 }
636 testcase << "test_mul " << to_string(Number::getMantissaScale())
637 << " upward";
638 {
639 auto const cSmall = std::to_array<Case>(
640 {{Number{7}, Number{8}, Number{56}},
641 {Number{1414213562373095, -15},
642 Number{1414213562373095, -15},
643 Number{2000000000000000, -15}},
644 {Number{-1414213562373095, -15},
645 Number{1414213562373095, -15},
646 Number{-1999999999999999, -15}},
647 {Number{-1414213562373095, -15},
648 Number{-1414213562373095, -15},
649 Number{2000000000000000, -15}},
650 {Number{3214285714285706, -15},
651 Number{3111111111111119, -15},
652 Number{1000000000000000, -14}},
653 {Number{1000000000000000, -32768},
654 Number{1000000000000000, -32768},
655 Number{0}}});
656 auto const cLarge = std::to_array<Case>(
657 // Note that items with extremely large mantissas need to be
658 // calculated, because otherwise they overflow uint64. Items
659 // from C with larger mantissa
660 {
661 {Number{7}, Number{8}, Number{56}},
662 {Number{1414213562373095, -15},
663 Number{1414213562373095, -15},
664 Number{1999999999999999862, -18}},
665 {Number{-1414213562373095, -15},
666 Number{1414213562373095, -15},
667 Number{-1999999999999999861, -18}},
668 {Number{-1414213562373095, -15},
669 Number{-1414213562373095, -15},
670 Number{1999999999999999862, -18}},
671 {Number{3214285714285706, -15},
672 Number{3111111111111119, -15},
673 Number{999999999999999958, -17}},
674 {Number{1000000000000000000, -32768},
675 Number{1000000000000000000, -32768},
676 Number{0}},
677 // Items from cSmall expanded for the larger mantissa,
678 // except duplicates. Sadly, it looks like sqrt(2)^2 != 2
679 // with higher precision
680 {Number{1414213562373095049, -18},
681 Number{1414213562373095049, -18},
682 Number{2000000000000000001, -18}},
683 {Number{-1414213562373095048, -18},
684 Number{1414213562373095048, -18},
685 Number{-1999999999999999997, -18}},
686 {Number{-1414213562373095048, -18},
687 Number{-1414213562373095049, -18},
688 Number{2, 0}},
689 {Number{3214285714285714278, -18},
690 Number{3111111111111111119, -18},
691 Number{1000000000000000001, -17}},
692 // Maximum mantissa range - rounds up to minMantissa*10
693 // 1e19*1e19=1e38
696 Number{1, 38}},
697 // Maximum int64 range
698 // 85'070'591'730'234'615'847'396'907'784'232'501'249
701 Number{85'070'591'730'234'615'85, 19}},
702 });
703 tests(cSmall, cLarge);
704 }
705 testcase << "test_mul " << to_string(Number::getMantissaScale())
706 << " overflow";
707 {
708 bool caught = false;
709 try
710 {
711 Number{false, maxMantissa, 32768, Number::normalized{}} *
712 Number{
713 false,
715 32767,
717 }
718 catch (std::overflow_error const&)
719 {
720 caught = true;
721 }
722 BEAST_EXPECT(caught);
723 }
724 }
725
726 void
728 {
729 auto const scale = Number::getMantissaScale();
730 testcase << "test_div " << to_string(scale);
731
733 auto test = [this](auto const& c) {
734 for (auto const& [x, y, z] : c)
735 {
736 auto const result = x / y;
738 ss << x << " / " << y << " = " << result << ". Expected: " << z;
739 BEAST_EXPECTS(result == z, ss.str());
740 }
741 };
742 auto const maxMantissa = Number::maxMantissa();
743 auto tests = [&](auto const& cSmall, auto const& cLarge) {
744 if (scale == MantissaRange::small)
745 test(cSmall);
746 else
747 test(cLarge);
748 };
750 {
751 auto const cSmall = std::to_array<Case>(
752 {{Number{1}, Number{2}, Number{5, -1}},
753 {Number{1}, Number{10}, Number{1, -1}},
754 {Number{1}, Number{-10}, Number{-1, -1}},
755 {Number{0}, Number{100}, Number{0}},
756 {Number{1414213562373095, -10},
757 Number{1414213562373095, -10},
758 Number{1}},
759 {Number{9'999'999'999'999'999},
760 Number{1'000'000'000'000'000},
761 Number{9'999'999'999'999'999, -15}},
762 {Number{2}, Number{3}, Number{6'666'666'666'666'667, -16}},
763 {Number{-2}, Number{3}, Number{-6'666'666'666'666'667, -16}},
764 {Number{1}, Number{7}, Number{1'428'571'428'571'428, -16}}});
765 auto const cLarge = std::to_array<Case>(
766 // Note that items with extremely large mantissas need to be
767 // calculated, because otherwise they overflow uint64. Items
768 // from C with larger mantissa
769 {{Number{1}, Number{2}, Number{5, -1}},
770 {Number{1}, Number{10}, Number{1, -1}},
771 {Number{1}, Number{-10}, Number{-1, -1}},
772 {Number{0}, Number{100}, Number{0}},
773 {Number{1414213562373095, -10},
774 Number{1414213562373095, -10},
775 Number{1}},
776 {Number{9'999'999'999'999'999},
777 Number{1'000'000'000'000'000},
778 Number{9'999'999'999'999'999, -15}},
779 {Number{2}, Number{3}, Number{6'666'666'666'666'666'667, -19}},
780 {Number{-2},
781 Number{3},
782 Number{-6'666'666'666'666'666'667, -19}},
783 {Number{1}, Number{7}, Number{1'428'571'428'571'428'571, -19}},
784 // Items from cSmall expanded for the larger mantissa, except
785 // duplicates.
786 {Number{1414213562373095049, -13},
787 Number{1414213562373095049, -13},
788 Number{1}},
790 Number{1'000'000'000'000'000'000},
791 Number{false, maxMantissa, -18, Number::normalized{}}}});
792 tests(cSmall, cLarge);
793 }
794 testcase << "test_div " << to_string(Number::getMantissaScale())
795 << " towards_zero";
797 {
798 auto const cSmall = std::to_array<Case>(
799 {{Number{1}, Number{2}, Number{5, -1}},
800 {Number{1}, Number{10}, Number{1, -1}},
801 {Number{1}, Number{-10}, Number{-1, -1}},
802 {Number{0}, Number{100}, Number{0}},
803 {Number{1414213562373095, -10},
804 Number{1414213562373095, -10},
805 Number{1}},
806 {Number{9'999'999'999'999'999},
807 Number{1'000'000'000'000'000},
808 Number{9'999'999'999'999'999, -15}},
809 {Number{2}, Number{3}, Number{6'666'666'666'666'666, -16}},
810 {Number{-2}, Number{3}, Number{-6'666'666'666'666'666, -16}},
811 {Number{1}, Number{7}, Number{1'428'571'428'571'428, -16}}});
812 auto const cLarge = std::to_array<Case>(
813 // Note that items with extremely large mantissas need to be
814 // calculated, because otherwise they overflow uint64. Items
815 // from C with larger mantissa
816 {{Number{1}, Number{2}, Number{5, -1}},
817 {Number{1}, Number{10}, Number{1, -1}},
818 {Number{1}, Number{-10}, Number{-1, -1}},
819 {Number{0}, Number{100}, Number{0}},
820 {Number{1414213562373095, -10},
821 Number{1414213562373095, -10},
822 Number{1}},
823 {Number{9'999'999'999'999'999},
824 Number{1'000'000'000'000'000},
825 Number{9'999'999'999'999'999, -15}},
826 {Number{2}, Number{3}, Number{6'666'666'666'666'666'666, -19}},
827 {Number{-2},
828 Number{3},
829 Number{-6'666'666'666'666'666'666, -19}},
830 {Number{1}, Number{7}, Number{1'428'571'428'571'428'571, -19}},
831 // Items from cSmall expanded for the larger mantissa, except
832 // duplicates.
833 {Number{1414213562373095049, -13},
834 Number{1414213562373095049, -13},
835 Number{1}},
837 Number{1'000'000'000'000'000'000},
838 Number{false, maxMantissa, -18, Number::normalized{}}}});
839 tests(cSmall, cLarge);
840 }
841 testcase << "test_div " << to_string(Number::getMantissaScale())
842 << " downward";
844 {
845 auto const cSmall = std::to_array<Case>(
846 {{Number{1}, Number{2}, Number{5, -1}},
847 {Number{1}, Number{10}, Number{1, -1}},
848 {Number{1}, Number{-10}, Number{-1, -1}},
849 {Number{0}, Number{100}, Number{0}},
850 {Number{1414213562373095, -10},
851 Number{1414213562373095, -10},
852 Number{1}},
853 {Number{9'999'999'999'999'999},
854 Number{1'000'000'000'000'000},
855 Number{9'999'999'999'999'999, -15}},
856 {Number{2}, Number{3}, Number{6'666'666'666'666'666, -16}},
857 {Number{-2}, Number{3}, Number{-6'666'666'666'666'667, -16}},
858 {Number{1}, Number{7}, Number{1'428'571'428'571'428, -16}}});
859 auto const cLarge = std::to_array<Case>(
860 // Note that items with extremely large mantissas need to be
861 // calculated, because otherwise they overflow uint64. Items
862 // from C with larger mantissa
863 {{Number{1}, Number{2}, Number{5, -1}},
864 {Number{1}, Number{10}, Number{1, -1}},
865 {Number{1}, Number{-10}, Number{-1, -1}},
866 {Number{0}, Number{100}, Number{0}},
867 {Number{1414213562373095, -10},
868 Number{1414213562373095, -10},
869 Number{1}},
870 {Number{9'999'999'999'999'999},
871 Number{1'000'000'000'000'000},
872 Number{9'999'999'999'999'999, -15}},
873 {Number{2}, Number{3}, Number{6'666'666'666'666'666'666, -19}},
874 {Number{-2},
875 Number{3},
876 Number{-6'666'666'666'666'666'667, -19}},
877 {Number{1}, Number{7}, Number{1'428'571'428'571'428'571, -19}},
878 // Items from cSmall expanded for the larger mantissa, except
879 // duplicates.
880 {Number{1414213562373095049, -13},
881 Number{1414213562373095049, -13},
882 Number{1}},
884 Number{1'000'000'000'000'000'000},
885 Number{false, maxMantissa, -18, Number::normalized{}}}});
886 tests(cSmall, cLarge);
887 }
888 testcase << "test_div " << to_string(Number::getMantissaScale())
889 << " upward";
891 {
892 auto const cSmall = std::to_array<Case>(
893 {{Number{1}, Number{2}, Number{5, -1}},
894 {Number{1}, Number{10}, Number{1, -1}},
895 {Number{1}, Number{-10}, Number{-1, -1}},
896 {Number{0}, Number{100}, Number{0}},
897 {Number{1414213562373095, -10},
898 Number{1414213562373095, -10},
899 Number{1}},
900 {Number{9'999'999'999'999'999},
901 Number{1'000'000'000'000'000},
902 Number{9'999'999'999'999'999, -15}},
903 {Number{2}, Number{3}, Number{6'666'666'666'666'667, -16}},
904 {Number{-2}, Number{3}, Number{-6'666'666'666'666'666, -16}},
905 {Number{1}, Number{7}, Number{1'428'571'428'571'429, -16}}});
906 auto const cLarge = std::to_array<Case>(
907 // Note that items with extremely large mantissas need to be
908 // calculated, because otherwise they overflow uint64. Items
909 // from C with larger mantissa
910 {{Number{1}, Number{2}, Number{5, -1}},
911 {Number{1}, Number{10}, Number{1, -1}},
912 {Number{1}, Number{-10}, Number{-1, -1}},
913 {Number{0}, Number{100}, Number{0}},
914 {Number{1414213562373095, -10},
915 Number{1414213562373095, -10},
916 Number{1}},
917 {Number{9'999'999'999'999'999},
918 Number{1'000'000'000'000'000},
919 Number{9'999'999'999'999'999, -15}},
920 {Number{2}, Number{3}, Number{6'666'666'666'666'666'667, -19}},
921 {Number{-2},
922 Number{3},
923 Number{-6'666'666'666'666'666'666, -19}},
924 {Number{1}, Number{7}, Number{1'428'571'428'571'428'572, -19}},
925 // Items from cSmall expanded for the larger mantissa, except
926 // duplicates.
927 {Number{1414213562373095049, -13},
928 Number{1414213562373095049, -13},
929 Number{1}},
931 Number{1'000'000'000'000'000'000},
932 Number{false, maxMantissa, -18, Number::normalized{}}}});
933 tests(cSmall, cLarge);
934 }
935 testcase << "test_div " << to_string(Number::getMantissaScale())
936 << " overflow";
937 bool caught = false;
938 try
939 {
940 Number{1000000000000000, -15} / Number{0};
941 }
942 catch (std::overflow_error const&)
943 {
944 caught = true;
945 }
946 BEAST_EXPECT(caught);
947 }
948
949 void
951 {
952 auto const scale = Number::getMantissaScale();
953 testcase << "test_root " << to_string(scale);
954
956 auto test = [this](auto const& c) {
957 for (auto const& [x, y, z] : c)
958 {
959 auto const result = root(x, y);
961 ss << "root(" << x << ", " << y << ") = " << result
962 << ". Expected: " << z;
963 BEAST_EXPECTS(result == z, ss.str());
964 }
965 };
966 /*
967 auto tests = [&](auto const& cSmall, auto const& cLarge) {
968 test(cSmall);
969 if (scale != MantissaRange::small)
970 test(cLarge);
971 };
972 */
973
974 auto const cSmall = std::to_array<Case>(
975 {{Number{2}, 2, Number{1414213562373095049, -18}},
976 {Number{2'000'000}, 2, Number{1414213562373095049, -15}},
977 {Number{2, -30}, 2, Number{1414213562373095049, -33}},
978 {Number{-27}, 3, Number{-3}},
979 {Number{1}, 5, Number{1}},
980 {Number{-1}, 0, Number{1}},
981 {Number{5, -1}, 0, Number{0}},
982 {Number{0}, 5, Number{0}},
983 {Number{5625, -4}, 2, Number{75, -2}}});
984 auto const cLarge = std::to_array<Case>({
985 {Number{false, Number::maxMantissa() - 9, -1, Number::normalized{}},
986 2,
987 Number{false, 999'999'999'999'999'999, -9, Number::normalized{}}},
988 {Number{false, Number::maxMantissa() - 9, 0, Number::normalized{}},
989 2,
990 Number{
991 false, 3'162'277'660'168'379'330, -9, Number::normalized{}}},
993 2,
994 Number{false, 3'037'000'499'976049692, -9, Number::normalized{}}},
996 4,
997 Number{false, 55'108'98747006743627, -14, Number::normalized{}}},
998 });
999 test(cSmall);
1001 {
1003 test(cLarge);
1004 }
1005 bool caught = false;
1006 try
1007 {
1008 (void)root(Number{-2}, 0);
1009 }
1010 catch (std::overflow_error const&)
1011 {
1012 caught = true;
1013 }
1014 BEAST_EXPECT(caught);
1015 caught = false;
1016 try
1017 {
1018 (void)root(Number{-2}, 4);
1019 }
1020 catch (std::overflow_error const&)
1021 {
1022 caught = true;
1023 }
1024 BEAST_EXPECT(caught);
1025 }
1026
1027 void
1029 {
1030 auto const scale = Number::getMantissaScale();
1031 testcase << "test_root2 " << to_string(scale);
1032
1033 auto test = [this](auto const& c) {
1034 for (auto const& x : c)
1035 {
1036 auto const expected = root(x, 2);
1037 auto const result = root2(x);
1039 ss << "root2(" << x << ") = " << result
1040 << ". Expected: " << expected;
1041 BEAST_EXPECTS(result == expected, ss.str());
1042 }
1043 };
1044
1045 auto const cSmall = std::to_array<Number>({
1046 Number{2},
1047 Number{2'000'000},
1048 Number{2, -30},
1049 Number{27},
1050 Number{1},
1051 Number{5, -1},
1052 Number{0},
1053 Number{5625, -4},
1055 });
1056 test(cSmall);
1057 bool caught = false;
1058 try
1059 {
1060 (void)root2(Number{-2});
1061 }
1062 catch (std::overflow_error const&)
1063 {
1064 caught = true;
1065 }
1066 BEAST_EXPECT(caught);
1067 }
1068
1069 void
1071 {
1072 testcase << "test_power1 " << to_string(Number::getMantissaScale());
1074 Case c[]{
1075 {Number{64}, 0, Number{1}},
1076 {Number{64}, 1, Number{64}},
1077 {Number{64}, 2, Number{4096}},
1078 {Number{-64}, 2, Number{4096}},
1079 {Number{64}, 3, Number{262144}},
1080 {Number{-64}, 3, Number{-262144}},
1081 {Number{64},
1082 11,
1083 Number{false, 7378697629483820646ULL, 1, Number::normalized{}}},
1084 {Number{-64},
1085 11,
1086 Number{true, 7378697629483820646ULL, 1, Number::normalized{}}}};
1087 for (auto const& [x, y, z] : c)
1088 BEAST_EXPECT((power(x, y) == z));
1089 }
1090
1091 void
1093 {
1094 testcase << "test_power2 " << to_string(Number::getMantissaScale());
1096 Case c[]{
1097 {Number{1}, 3, 7, Number{1}},
1098 {Number{-1}, 1, 0, Number{1}},
1099 {Number{-1, -1}, 1, 0, Number{0}},
1100 {Number{16}, 0, 5, Number{1}},
1101 {Number{34}, 3, 3, Number{34}},
1102 {Number{4}, 3, 2, Number{8}}};
1103 for (auto const& [x, n, d, z] : c)
1104 BEAST_EXPECT((power(x, n, d) == z));
1105 bool caught = false;
1106 try
1107 {
1108 (void)power(Number{7}, 0, 0);
1109 }
1110 catch (std::overflow_error const&)
1111 {
1112 caught = true;
1113 }
1114 BEAST_EXPECT(caught);
1115 caught = false;
1116 try
1117 {
1118 (void)power(Number{7}, 1, 0);
1119 }
1120 catch (std::overflow_error const&)
1121 {
1122 caught = true;
1123 }
1124 BEAST_EXPECT(caught);
1125 caught = false;
1126 try
1127 {
1128 (void)power(Number{-1, -1}, 3, 2);
1129 }
1130 catch (std::overflow_error const&)
1131 {
1132 caught = true;
1133 }
1134 BEAST_EXPECT(caught);
1135 }
1136
1137 void
1139 {
1140 testcase << "testConversions " << to_string(Number::getMantissaScale());
1141
1142 IOUAmount x{5, 6};
1143 Number y = x;
1144 BEAST_EXPECT((y == Number{5, 6}));
1145 IOUAmount z{y};
1146 BEAST_EXPECT(x == z);
1147 XRPAmount xrp{500};
1148 STAmount st = xrp;
1149 Number n = st;
1150 BEAST_EXPECT(XRPAmount{n} == xrp);
1151 IOUAmount x0{0, 0};
1152 Number y0 = x0;
1153 BEAST_EXPECT((y0 == Number{0}));
1154 IOUAmount z0{y0};
1155 BEAST_EXPECT(x0 == z0);
1156 XRPAmount xrp0{0};
1157 Number n0 = xrp0;
1158 BEAST_EXPECT(n0 == Number{0});
1159 XRPAmount xrp1{n0};
1160 BEAST_EXPECT(xrp1 == xrp0);
1161 }
1162
1163 void
1165 {
1166 testcase << "test_to_integer " << to_string(Number::getMantissaScale());
1169 {
1170 Case c[]{
1171 {Number{0}, 0},
1172 {Number{1}, 1},
1173 {Number{2}, 2},
1174 {Number{3}, 3},
1175 {Number{-1}, -1},
1176 {Number{-2}, -2},
1177 {Number{-3}, -3},
1178 {Number{10}, 10},
1179 {Number{99}, 99},
1180 {Number{1155}, 1155},
1181 {Number{9'999'999'999'999'999, 0}, 9'999'999'999'999'999},
1182 {Number{9'999'999'999'999'999, 1}, 99'999'999'999'999'990},
1183 {Number{9'999'999'999'999'999, 2}, 999'999'999'999'999'900},
1184 {Number{-9'999'999'999'999'999, 2}, -999'999'999'999'999'900},
1185 {Number{15, -1}, 2},
1186 {Number{14, -1}, 1},
1187 {Number{16, -1}, 2},
1188 {Number{25, -1}, 2},
1189 {Number{6, -1}, 1},
1190 {Number{5, -1}, 0},
1191 {Number{4, -1}, 0},
1192 {Number{-15, -1}, -2},
1193 {Number{-14, -1}, -1},
1194 {Number{-16, -1}, -2},
1195 {Number{-25, -1}, -2},
1196 {Number{-6, -1}, -1},
1197 {Number{-5, -1}, 0},
1198 {Number{-4, -1}, 0}};
1199 for (auto const& [x, y] : c)
1200 {
1201 auto j = static_cast<std::int64_t>(x);
1202 BEAST_EXPECT(j == y);
1203 }
1204 }
1205 auto prev_mode = Number::setround(Number::towards_zero);
1206 BEAST_EXPECT(prev_mode == Number::to_nearest);
1207 {
1208 Case c[]{
1209 {Number{0}, 0},
1210 {Number{1}, 1},
1211 {Number{2}, 2},
1212 {Number{3}, 3},
1213 {Number{-1}, -1},
1214 {Number{-2}, -2},
1215 {Number{-3}, -3},
1216 {Number{10}, 10},
1217 {Number{99}, 99},
1218 {Number{1155}, 1155},
1219 {Number{9'999'999'999'999'999, 0}, 9'999'999'999'999'999},
1220 {Number{9'999'999'999'999'999, 1}, 99'999'999'999'999'990},
1221 {Number{9'999'999'999'999'999, 2}, 999'999'999'999'999'900},
1222 {Number{-9'999'999'999'999'999, 2}, -999'999'999'999'999'900},
1223 {Number{15, -1}, 1},
1224 {Number{14, -1}, 1},
1225 {Number{16, -1}, 1},
1226 {Number{25, -1}, 2},
1227 {Number{6, -1}, 0},
1228 {Number{5, -1}, 0},
1229 {Number{4, -1}, 0},
1230 {Number{-15, -1}, -1},
1231 {Number{-14, -1}, -1},
1232 {Number{-16, -1}, -1},
1233 {Number{-25, -1}, -2},
1234 {Number{-6, -1}, 0},
1235 {Number{-5, -1}, 0},
1236 {Number{-4, -1}, 0}};
1237 for (auto const& [x, y] : c)
1238 {
1239 auto j = static_cast<std::int64_t>(x);
1240 BEAST_EXPECT(j == y);
1241 }
1242 }
1244 BEAST_EXPECT(prev_mode == Number::towards_zero);
1245 {
1246 Case c[]{
1247 {Number{0}, 0},
1248 {Number{1}, 1},
1249 {Number{2}, 2},
1250 {Number{3}, 3},
1251 {Number{-1}, -1},
1252 {Number{-2}, -2},
1253 {Number{-3}, -3},
1254 {Number{10}, 10},
1255 {Number{99}, 99},
1256 {Number{1155}, 1155},
1257 {Number{9'999'999'999'999'999, 0}, 9'999'999'999'999'999},
1258 {Number{9'999'999'999'999'999, 1}, 99'999'999'999'999'990},
1259 {Number{9'999'999'999'999'999, 2}, 999'999'999'999'999'900},
1260 {Number{-9'999'999'999'999'999, 2}, -999'999'999'999'999'900},
1261 {Number{15, -1}, 1},
1262 {Number{14, -1}, 1},
1263 {Number{16, -1}, 1},
1264 {Number{25, -1}, 2},
1265 {Number{6, -1}, 0},
1266 {Number{5, -1}, 0},
1267 {Number{4, -1}, 0},
1268 {Number{-15, -1}, -2},
1269 {Number{-14, -1}, -2},
1270 {Number{-16, -1}, -2},
1271 {Number{-25, -1}, -3},
1272 {Number{-6, -1}, -1},
1273 {Number{-5, -1}, -1},
1274 {Number{-4, -1}, -1}};
1275 for (auto const& [x, y] : c)
1276 {
1277 auto j = static_cast<std::int64_t>(x);
1278 BEAST_EXPECT(j == y);
1279 }
1280 }
1281 prev_mode = Number::setround(Number::upward);
1282 BEAST_EXPECT(prev_mode == Number::downward);
1283 {
1284 Case c[]{
1285 {Number{0}, 0},
1286 {Number{1}, 1},
1287 {Number{2}, 2},
1288 {Number{3}, 3},
1289 {Number{-1}, -1},
1290 {Number{-2}, -2},
1291 {Number{-3}, -3},
1292 {Number{10}, 10},
1293 {Number{99}, 99},
1294 {Number{1155}, 1155},
1295 {Number{9'999'999'999'999'999, 0}, 9'999'999'999'999'999},
1296 {Number{9'999'999'999'999'999, 1}, 99'999'999'999'999'990},
1297 {Number{9'999'999'999'999'999, 2}, 999'999'999'999'999'900},
1298 {Number{-9'999'999'999'999'999, 2}, -999'999'999'999'999'900},
1299 {Number{15, -1}, 2},
1300 {Number{14, -1}, 2},
1301 {Number{16, -1}, 2},
1302 {Number{25, -1}, 3},
1303 {Number{6, -1}, 1},
1304 {Number{5, -1}, 1},
1305 {Number{4, -1}, 1},
1306 {Number{-15, -1}, -1},
1307 {Number{-14, -1}, -1},
1308 {Number{-16, -1}, -1},
1309 {Number{-25, -1}, -2},
1310 {Number{-6, -1}, 0},
1311 {Number{-5, -1}, 0},
1312 {Number{-4, -1}, 0}};
1313 for (auto const& [x, y] : c)
1314 {
1315 auto j = static_cast<std::int64_t>(x);
1316 BEAST_EXPECT(j == y);
1317 }
1318 }
1319 bool caught = false;
1320 try
1321 {
1322 (void)static_cast<std::int64_t>(Number{9223372036854776, 3});
1323 }
1324 catch (std::overflow_error const&)
1325 {
1326 caught = true;
1327 }
1328 BEAST_EXPECT(caught);
1329 }
1330
1331 void
1333 {
1334 testcase << "test_squelch " << to_string(Number::getMantissaScale());
1335 Number limit{1, -6};
1336 BEAST_EXPECT((squelch(Number{2, -6}, limit) == Number{2, -6}));
1337 BEAST_EXPECT((squelch(Number{1, -6}, limit) == Number{1, -6}));
1338 BEAST_EXPECT((squelch(Number{9, -7}, limit) == Number{0}));
1339 BEAST_EXPECT((squelch(Number{-2, -6}, limit) == Number{-2, -6}));
1340 BEAST_EXPECT((squelch(Number{-1, -6}, limit) == Number{-1, -6}));
1341 BEAST_EXPECT((squelch(Number{-9, -7}, limit) == Number{0}));
1342 }
1343
1344 void
1346 {
1347 auto const scale = Number::getMantissaScale();
1348 testcase << "testToString " << to_string(scale);
1349
1350 auto test = [this](Number const& n, std::string const& expected) {
1351 auto const result = to_string(n);
1353 ss << "to_string(" << result << "). Expected: " << expected;
1354 BEAST_EXPECTS(result == expected, ss.str());
1355 };
1356
1357 test(Number(-2, 0), "-2");
1358 test(Number(0, 0), "0");
1359 test(Number(2, 0), "2");
1360 test(Number(25, -3), "0.025");
1361 test(Number(-25, -3), "-0.025");
1362 test(Number(25, 1), "250");
1363 test(Number(-25, 1), "-250");
1364 test(Number(2, 20), "2e20");
1365 test(Number(-2, -20), "-2e-20");
1366 // Test the edges
1367 // ((exponent < -(25)) || (exponent > -(5)))))
1368 // or ((exponent < -(28)) || (exponent > -(8)))))
1369 test(Number(2, -10), "0.0000000002");
1370 test(Number(2, -11), "2e-11");
1371
1372 test(Number(-2, 10), "-20000000000");
1373 test(Number(-2, 11), "-2e11");
1374
1375 switch (scale)
1376 {
1378
1379 test(Number::min(), "1e-32753");
1380 test(Number::max(), "9999999999999999e32768");
1381 test(Number::lowest(), "-9999999999999999e32768");
1382 {
1384
1385 auto const maxMantissa = Number::maxMantissa();
1386 BEAST_EXPECT(maxMantissa == 9'999'999'999'999'999);
1387 test(
1388 Number{
1389 false,
1390 maxMantissa * 1000 + 999,
1391 -3,
1393 "9999999999999999");
1394 test(
1395 Number{
1396 true,
1397 maxMantissa * 1000 + 999,
1398 -3,
1400 "-9999999999999999");
1401
1402 test(
1404 "9223372036854775");
1405 test(
1407 "-9223372036854775");
1408
1409 test(
1411 "-9223372036854775e3");
1412 test(
1414 "9223372036854775e3");
1415 }
1416 break;
1418 // Test the edges
1419 // ((exponent < -(28)) || (exponent > -(8)))))
1420 test(Number::min(), "1e-32750");
1421 test(Number::max(), "9223372036854775807e32768");
1422 test(Number::lowest(), "-9223372036854775807e32768");
1423 {
1425
1426 auto const maxMantissa = Number::maxMantissa();
1427 BEAST_EXPECT(maxMantissa == 9'999'999'999'999'999'999ULL);
1428 test(
1430 "9999999999999999990");
1431 test(
1433 "-9999999999999999990");
1434
1435 test(
1437 "9223372036854775807");
1438 test(
1440 "-9223372036854775807");
1441
1442 // Because the absolute value of min is larger than max, it
1443 // will be scaled down to fit under max. Since we're
1444 // rounding towards zero, the 8 at the end is dropped.
1445 test(
1447 "-9223372036854775800");
1448 test(
1450 "9223372036854775800");
1451 }
1452
1453 test(
1455 "9223372036854775810");
1456 test(
1458 "-9223372036854775810");
1459 break;
1460 default:
1461 BEAST_EXPECT(false);
1462 }
1463 }
1464
1465 void
1467 {
1468 testcase << "test_relationals "
1470 BEAST_EXPECT(!(Number{100} < Number{10}));
1471 BEAST_EXPECT(Number{100} > Number{10});
1472 BEAST_EXPECT(Number{100} >= Number{10});
1473 BEAST_EXPECT(!(Number{100} <= Number{10}));
1474 }
1475
1476 void
1478 {
1479 testcase << "test_stream " << to_string(Number::getMantissaScale());
1480 Number x{100};
1482 os << x;
1483 BEAST_EXPECT(os.str() == to_string(x));
1484 }
1485
1486 void
1488 {
1489 testcase << "test_inc_dec " << to_string(Number::getMantissaScale());
1490 Number x{100};
1491 Number y = +x;
1492 BEAST_EXPECT(x == y);
1493 BEAST_EXPECT(x++ == y);
1494 BEAST_EXPECT(x == Number{101});
1495 BEAST_EXPECT(x-- == Number{101});
1496 BEAST_EXPECT(x == y);
1497 }
1498
1499 void
1501 {
1502 NumberSO stNumberSO{true};
1503 Issue const issue;
1504 Number const n{7'518'783'80596, -5};
1506 auto res2 = STAmount{issue, n};
1507 BEAST_EXPECT(res2 == STAmount{7518784});
1508
1510 res2 = STAmount{issue, n};
1511 BEAST_EXPECT(res2 == STAmount{7518783});
1512
1514 res2 = STAmount{issue, n};
1515 BEAST_EXPECT(res2 == STAmount{7518783});
1516
1518 res2 = STAmount{issue, n};
1519 BEAST_EXPECT(res2 == STAmount{7518784});
1520 }
1521
1522 void
1524 {
1525 BEAST_EXPECT(Number(25, +1).truncate() == Number(250, 0));
1526 BEAST_EXPECT(Number(25, 0).truncate() == Number(25, 0));
1527 BEAST_EXPECT(Number(25, -1).truncate() == Number(2, 0));
1528 BEAST_EXPECT(Number(25, -2).truncate() == Number(0, 0));
1529 BEAST_EXPECT(Number(99, -2).truncate() == Number(0, 0));
1530
1531 BEAST_EXPECT(Number(-25, +1).truncate() == Number(-250, 0));
1532 BEAST_EXPECT(Number(-25, 0).truncate() == Number(-25, 0));
1533 BEAST_EXPECT(Number(-25, -1).truncate() == Number(-2, 0));
1534 BEAST_EXPECT(Number(-25, -2).truncate() == Number(0, 0));
1535 BEAST_EXPECT(Number(-99, -2).truncate() == Number(0, 0));
1536
1537 BEAST_EXPECT(Number(0, 0).truncate() == Number(0, 0));
1538 BEAST_EXPECT(Number(0, 30000).truncate() == Number(0, 0));
1539 BEAST_EXPECT(Number(0, -30000).truncate() == Number(0, 0));
1540 BEAST_EXPECT(Number(100, -30000).truncate() == Number(0, 0));
1541 BEAST_EXPECT(Number(100, -30000).truncate() == Number(0, 0));
1542 BEAST_EXPECT(Number(-100, -30000).truncate() == Number(0, 0));
1543 BEAST_EXPECT(Number(-100, -30000).truncate() == Number(0, 0));
1544 }
1545
1546 void
1548 {
1549 // Test that rounding works as expected.
1550 testcase("Rounding");
1551
1552 using NumberRoundings = std::map<Number::rounding_mode, std::int64_t>;
1553
1554 std::map<Number, NumberRoundings> const expected{
1555 // Positive numbers
1556 {Number{13, -1},
1557 {{Number::to_nearest, 1},
1559 {Number::downward, 1},
1560 {Number::upward, 2}}},
1561 {Number{23, -1},
1562 {{Number::to_nearest, 2},
1564 {Number::downward, 2},
1565 {Number::upward, 3}}},
1566 {Number{15, -1},
1567 {{Number::to_nearest, 2},
1569 {Number::downward, 1},
1570 {Number::upward, 2}}},
1571 {Number{25, -1},
1572 {{Number::to_nearest, 2},
1574 {Number::downward, 2},
1575 {Number::upward, 3}}},
1576 {Number{152, -2},
1577 {{Number::to_nearest, 2},
1579 {Number::downward, 1},
1580 {Number::upward, 2}}},
1581 {Number{252, -2},
1582 {{Number::to_nearest, 3},
1584 {Number::downward, 2},
1585 {Number::upward, 3}}},
1586 {Number{17, -1},
1587 {{Number::to_nearest, 2},
1589 {Number::downward, 1},
1590 {Number::upward, 2}}},
1591 {Number{27, -1},
1592 {{Number::to_nearest, 3},
1594 {Number::downward, 2},
1595 {Number::upward, 3}}},
1596
1597 // Negative numbers
1598 {Number{-13, -1},
1599 {{Number::to_nearest, -1},
1601 {Number::downward, -2},
1602 {Number::upward, -1}}},
1603 {Number{-23, -1},
1604 {{Number::to_nearest, -2},
1606 {Number::downward, -3},
1607 {Number::upward, -2}}},
1608 {Number{-15, -1},
1609 {{Number::to_nearest, -2},
1611 {Number::downward, -2},
1612 {Number::upward, -1}}},
1613 {Number{-25, -1},
1614 {{Number::to_nearest, -2},
1616 {Number::downward, -3},
1617 {Number::upward, -2}}},
1618 {Number{-152, -2},
1619 {{Number::to_nearest, -2},
1621 {Number::downward, -2},
1622 {Number::upward, -1}}},
1623 {Number{-252, -2},
1624 {{Number::to_nearest, -3},
1626 {Number::downward, -3},
1627 {Number::upward, -2}}},
1628 {Number{-17, -1},
1629 {{Number::to_nearest, -2},
1631 {Number::downward, -2},
1632 {Number::upward, -1}}},
1633 {Number{-27, -1},
1634 {{Number::to_nearest, -3},
1636 {Number::downward, -3},
1637 {Number::upward, -2}}},
1638 };
1639
1640 for (auto const& [num, roundings] : expected)
1641 {
1642 for (auto const& [mode, val] : roundings)
1643 {
1644 NumberRoundModeGuard g{mode};
1645 auto const res = static_cast<std::int64_t>(num);
1646 BEAST_EXPECTS(
1647 res == val,
1648 to_string(num) + " with mode " + std::to_string(mode) +
1649 " expected " + std::to_string(val) + " got " +
1650 std::to_string(res));
1651 }
1652 }
1653 }
1654
1655 void
1657 {
1658 auto const scale = Number::getMantissaScale();
1659 testcase << "std::int64_t " << to_string(scale);
1660
1661 // Control case
1662 BEAST_EXPECT(Number::maxMantissa() > 10);
1663 Number ten{10};
1664 BEAST_EXPECT(ten.exponent() <= 0);
1665
1666 if (scale == MantissaRange::small)
1667 {
1668 BEAST_EXPECT(
1670 BEAST_EXPECT(Number::maxMantissa() < INITIAL_XRP.drops());
1671 Number const initalXrp{INITIAL_XRP};
1672 BEAST_EXPECT(initalXrp.exponent() > 0);
1673
1674 Number const maxInt64{Number::maxRep};
1675 BEAST_EXPECT(maxInt64.exponent() > 0);
1676 // 85'070'591'730'234'615'865'843'651'857'942'052'864 - 38 digits
1677 BEAST_EXPECT(
1678 (power(maxInt64, 2) == Number{85'070'591'730'234'62, 22}));
1679
1680 Number const max =
1682 BEAST_EXPECT(max.exponent() <= 0);
1683 // 99'999'999'999'999'980'000'000'000'000'001 - 32 digits
1684 BEAST_EXPECT((power(max, 2) == Number{99'999'999'999'999'98, 16}));
1685 }
1686 else
1687 {
1688 BEAST_EXPECT(
1690 BEAST_EXPECT(Number::maxMantissa() > INITIAL_XRP.drops());
1691 Number const initalXrp{INITIAL_XRP};
1692 BEAST_EXPECT(initalXrp.exponent() <= 0);
1693
1694 Number const maxInt64{Number::maxRep};
1695 BEAST_EXPECT(maxInt64.exponent() <= 0);
1696 // 85'070'591'730'234'615'847'396'907'784'232'501'249 - 38 digits
1697 BEAST_EXPECT(
1698 (power(maxInt64, 2) == Number{85'070'591'730'234'615'85, 19}));
1699
1701
1702 auto const maxMantissa = Number::maxMantissa();
1703 Number const max =
1705 BEAST_EXPECT(max.mantissa() == maxMantissa / 10);
1706 BEAST_EXPECT(max.exponent() == 1);
1707 // 99'999'999'999'999'999'800'000'000'000'000'000'100 - also 38
1708 // digits
1709 BEAST_EXPECT((
1710 power(max, 2) ==
1711 Number{false, maxMantissa / 10 - 1, 20, Number::normalized{}}));
1712 }
1713 }
1714
1715 void
1716 run() override
1717 {
1718 for (auto const scale : {MantissaRange::small, MantissaRange::large})
1719 {
1720 NumberMantissaScaleGuard sg(scale);
1721 testZero();
1722 test_limits();
1723 testToString();
1724 test_add();
1725 test_sub();
1726 test_mul();
1727 test_div();
1728 test_root();
1729 test_root2();
1730 test_power1();
1731 test_power2();
1734 test_squelch();
1736 test_stream();
1737 test_inc_dec();
1739 test_truncate();
1740 testRounding();
1741 testInt64();
1742 }
1743 }
1744};
1745
1746BEAST_DEFINE_TESTSUITE(Number, basics, xrpl);
1747
1748} // namespace xrpl
A testsuite class.
Definition suite.h:52
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:152
bool expect(Condition const &shouldBeTrue)
Evaluate a test condition.
Definition suite.h:226
Floating point representation of amounts with high dynamic range.
Definition IOUAmount.h:27
A currency issued by an account.
Definition Issue.h:14
Sets the new scale and restores the old scale when it leaves scope.
Definition Number.h:836
RAII class to set and restore the Number switchover.
Definition IOUAmount.h:197
void run() override
Runs the suite.
Number is a floating point type that can represent a wide range of values.
Definition Number.h:211
static internalrep minMantissa()
Definition Number.h:417
static rounding_mode setround(rounding_mode mode)
Definition Number.cpp:40
static constexpr internalrep maxRep
Definition Number.h:224
static Number max() noexcept
Definition Number.h:696
static internalrep maxMantissa()
Definition Number.h:423
constexpr int exponent() const noexcept
Returns the exponent of the external view of the Number.
Definition Number.h:591
static MantissaRange::mantissa_scale getMantissaScale()
Returns which mantissa scale is currently in use for normalization.
Definition Number.cpp:46
static Number min() noexcept
Definition Number.h:690
static Number lowest() noexcept
Definition Number.h:703
static int mantissaLog()
Definition Number.h:429
constexpr value_type drops() const
Returns the number of drops.
Definition XRPAmount.h:158
T is_same_v
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:6
static std::int64_t constexpr minMantissa
Definition IOUAmount.cpp:48
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:611
Number root(Number f, unsigned d)
Definition Number.cpp:997
Number power(Number const &f, unsigned n)
Definition Number.cpp:974
static std::int64_t constexpr maxMantissa
Definition IOUAmount.cpp:49
Number root2(Number f)
Definition Number.cpp:1073
constexpr XRPAmount INITIAL_XRP
Configure the native currency.
constexpr Number squelch(Number const &x, Number const &limit) noexcept
Definition Number.h:771
T str(T... args)
T to_string(T... args)