xrpld
Loading...
Searching...
No Matches
Number_test.cpp
1#include <xrpl/basics/Number.h>
2#include <xrpl/beast/unit_test/suite.h>
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 <algorithm>
14#include <array>
15#include <cctype>
16#include <cstdint>
17#include <iomanip>
18#include <limits>
19#include <map>
20#include <sstream>
21#include <stdexcept>
22#include <string>
23#include <tuple>
24#include <utility>
25#include <vector>
26
27namespace xrpl {
28
30{
31 using BigInt = boost::multiprecision::cpp_int;
32
33 static std::string
34 fmt(BigInt const& value)
35 {
36 auto s = to_string(value);
37 std::string out;
38 int count = 0;
39 for (auto it = s.rbegin(); it != s.rend(); ++it)
40 {
41 if (count != 0 && count % 3 == 0 && (isdigit(*it) != 0))
42 out.insert(out.begin(), '_');
43 out.insert(out.begin(), *it);
44 ++count;
45 }
46 return out;
47 }
48
49 using dec = boost::multiprecision::cpp_dec_float_50;
50
51 template <class T = dec>
52 static T
53 pow10(int n)
54 {
55 if (n == 0)
56 return 1;
57 if (n == 1)
58 return 10;
59
60 if (n > 1)
61 {
62 auto r = pow10<T>(n / 2);
63 r *= r;
64 if (n % 2 != 0)
65 r *= 10;
66 return r;
67 }
68
69 // n < 0
70 T p = 1;
71 p /= pow10<T>(-n);
72 return p;
73 }
74
75 static std::string
76 fmt(dec const& v)
77 {
79 os << std::setprecision(40) << v;
80 return os.str();
81 }
82
83public:
84 void
86 {
88
89 for (Number const& z : {Number{0, 0}, Number{0}})
90 {
91 BEAST_EXPECT(z.mantissa() == 0);
92 BEAST_EXPECT(z.exponent() == Number{}.exponent());
93
94 BEAST_EXPECT((z + z) == z);
95 BEAST_EXPECT((z - z) == z);
96 BEAST_EXPECT(z == -z);
97 }
98 }
99
100 void
102 {
103 auto const scale = Number::getMantissaScale();
104 testcase << "test_limits " << to_string(scale);
105 bool caught = false;
106 auto const minMantissa = Number::minMantissa();
107 try
108 {
109 [[maybe_unused]] Number const x =
110 Number{false, minMantissa * 10, 32768, Number::Normalized{}};
111 }
112 catch (std::overflow_error const&)
113 {
114 caught = true;
115 }
116 BEAST_EXPECT(caught);
117
118 auto test = [this](auto const& x, auto const& y, int line) {
119 auto const result = x == y;
121 ss << x << " == " << y << " -> " << (result ? "true" : "false");
122 expect(result, ss.str(), __FILE__, line);
123 };
124
125 test(
126 Number{false, minMantissa * 10, 32767, Number::Normalized{}},
127 Number{false, minMantissa, 32768, Number::Normalized{}},
128 __LINE__);
129 test(Number{false, minMantissa, -32769, Number::Normalized{}}, Number{}, __LINE__);
130 test(
131 Number{false, minMantissa, 32000, Number::Normalized{}} * 1'000 +
132 Number{false, 1'500, 32000, Number::Normalized{}},
133 Number{false, minMantissa + 2, 32003, Number::Normalized{}},
134 __LINE__);
135 // 9,223,372,036,854,775,808
136
137 test(
140 ? Number{-9'223'372'036'854'776, 3}
141 : Number{true, 9'223'372'036'854'775'808ULL, 0, Number::Normalized{}},
142 __LINE__);
143 test(
145 scale == MantissaRange::MantissaScale::Small ? Number{-9'223'372'036'854'776, 3}
146 : Number{-9'223'372'036'854'775'807},
147 __LINE__);
148 test(
150 Number{
152 ? 9'223'372'036'854'776
154 18 - Number::mantissaLog()},
155 __LINE__);
156 caught = false;
157 try
158 {
159 [[maybe_unused]]
160 Number const q = Number{false, minMantissa, 32767, Number::Normalized{}} * 100;
161 }
162 catch (std::overflow_error const&)
163 {
164 caught = true;
165 }
166 BEAST_EXPECT(caught);
167 }
168
169 void
171 {
172 auto const scale = Number::getMantissaScale();
173 testcase << "test_add " << to_string(scale);
174
176 auto const cSmall = std::to_array<Case>(
177 {{Number{1'000'000'000'000'000, -15},
178 Number{6'555'555'555'555'555, -29},
179 Number{1'000'000'000'000'066, -15}},
180 {Number{-1'000'000'000'000'000, -15},
181 Number{-6'555'555'555'555'555, -29},
182 Number{-1'000'000'000'000'066, -15}},
183 {Number{-1'000'000'000'000'000, -15},
184 Number{6'555'555'555'555'555, -29},
185 Number{-9'999'999'999'999'344, -16}},
186 {Number{-6'555'555'555'555'555, -29},
187 Number{1'000'000'000'000'000, -15},
188 Number{9'999'999'999'999'344, -16}},
189 {Number{}, Number{5}, Number{5}},
190 {Number{5}, Number{}, Number{5}},
191 {Number{5'555'555'555'555'555, -32768},
192 Number{-5'555'555'555'555'554, -32768},
193 Number{0}},
194 {Number{-9'999'999'999'999'999, -31},
195 Number{1'000'000'000'000'000, -15},
196 Number{9'999'999'999'999'990, -16}}});
197 auto const cLarge = std::to_array<Case>(
198 // Note that items with extremely large mantissas need to be
199 // calculated, because otherwise they overflow uint64. Items from C
200 // with larger mantissa
201 {
202 {Number{1'000'000'000'000'000, -15},
203 Number{6'555'555'555'555'555, -29},
204 Number{1'000'000'000'000'065'556, -18}},
205 {Number{-1'000'000'000'000'000, -15},
206 Number{-6'555'555'555'555'555, -29},
207 Number{-1'000'000'000'000'065'556, -18}},
208 {Number{-1'000'000'000'000'000, -15},
209 Number{6'555'555'555'555'555, -29},
210 Number{true, 9'999'999'999'999'344'444ULL, -19, Number::Normalized{}}},
211 {Number{-6'555'555'555'555'555, -29},
212 Number{1'000'000'000'000'000, -15},
213 Number{false, 9'999'999'999'999'344'444ULL, -19, Number::Normalized{}}},
214 {Number{}, Number{5}, Number{5}},
215 {Number{5}, Number{}, Number{5}},
216 {Number{5'555'555'555'555'555'000, -32768},
217 Number{-5'555'555'555'555'554'000, -32768},
218 Number{0}},
219 {Number{-9'999'999'999'999'999, -31},
220 Number{1'000'000'000'000'000, -15},
221 Number{9'999'999'999'999'990, -16}},
222 // Items from cSmall expanded for the larger mantissa
223 {Number{1'000'000'000'000'000'000, -18},
224 Number{6'555'555'555'555'555'555, -35},
225 Number{1'000'000'000'000'000'066, -18}},
226 {Number{-1'000'000'000'000'000'000, -18},
227 Number{-6'555'555'555'555'555'555, -35},
228 Number{-1'000'000'000'000'000'066, -18}},
229 {Number{-1'000'000'000'000'000'000, -18},
230 Number{6'555'555'555'555'555'555, -35},
231 Number{true, 9'999'999'999'999'999'344ULL, -19, Number::Normalized{}}},
232 {Number{-6'555'555'555'555'555'555, -35},
233 Number{1'000'000'000'000'000'000, -18},
234 Number{false, 9'999'999'999'999'999'344ULL, -19, Number::Normalized{}}},
235 {Number{}, Number{5}, Number{5}},
236 {Number{5'555'555'555'555'555'555, -32768},
237 Number{-5'555'555'555'555'555'554, -32768},
238 Number{0}},
239 {Number{true, 9'999'999'999'999'999'999ULL, -37, Number::Normalized{}},
240 Number{1'000'000'000'000'000'000, -18},
241 Number{false, 9'999'999'999'999'999'990ULL, -19, Number::Normalized{}}},
243 // Test extremes
244 {
245 // Each Number operand rounds up, so the actual mantissa is
246 // minMantissa
247 Number{false, 9'999'999'999'999'999'999ULL, 0, Number::Normalized{}},
248 Number{false, 9'999'999'999'999'999'999ULL, 0, Number::Normalized{}},
249 Number{2, 19},
250 },
251 {
252 // Does not round. Mantissas are going to be > kMaxRep, so if
253 // added together as uint64_t's, the result will overflow.
254 // With addition using uint128_t, there's no problem. After
255 // normalizing, the resulting mantissa ends up less than
256 // kMaxRep.
257 Number{false, 9'999'999'999'999'999'990ULL, 0, Number::Normalized{}},
258 Number{false, 9'999'999'999'999'999'990ULL, 0, Number::Normalized{}},
259 Number{false, 1'999'999'999'999'999'998ULL, 1, Number::Normalized{}},
260 },
261 });
262 auto const cLargeLegacy = std::to_array<Case>({
264 });
265 auto const cLargeCorrected = std::to_array<Case>({
266 {Number{Number::kMaxRep}, Number{6, -1}, Number{(Number::kMaxRep / 10) + 1, 1}},
267 });
268 auto test = [this](auto const& c) {
269 for (auto const& [x, y, z] : c)
270 {
271 auto const result = x + y;
273 ss << x << " + " << y << " = " << result << ". Expected: " << z;
274 BEAST_EXPECTS(result == z, ss.str());
275 }
276 };
278 {
279 test(cSmall);
280 }
281 else
282 {
283 test(cLarge);
285 {
286 test(cLargeLegacy);
287 }
288 else
289 {
290 test(cLargeCorrected);
291 }
292 }
293 {
294 bool caught = false;
295 try
296 {
297 Number{false, Number::maxMantissa(), 32768, Number::Normalized{}} +
298 Number{false, Number::minMantissa(), 32767, Number::Normalized{}} * 5;
299 }
300 catch (std::overflow_error const&)
301 {
302 caught = true;
303 }
304 BEAST_EXPECT(caught);
305 }
306 }
307
308 void
310 {
311 auto const scale = Number::getMantissaScale();
312 testcase << "test_sub " << to_string(scale);
313
315 auto const cSmall = std::to_array<Case>(
316 {{Number{1'000'000'000'000'000, -15},
317 Number{6'555'555'555'555'555, -29},
318 Number{9'999'999'999'999'344, -16}},
319 {Number{6'555'555'555'555'555, -29},
320 Number{1'000'000'000'000'000, -15},
321 Number{-9'999'999'999'999'344, -16}},
322 {Number{1'000'000'000'000'000, -15}, Number{1'000'000'000'000'000, -15}, Number{0}},
323 {Number{1'000'000'000'000'000, -15},
324 Number{1'000'000'000'000'001, -15},
325 Number{-1'000'000'000'000'000, -30}},
326 {Number{1'000'000'000'000'001, -15},
327 Number{1'000'000'000'000'000, -15},
328 Number{1'000'000'000'000'000, -30}}});
329 auto const cLarge = std::to_array<Case>(
330 // Note that items with extremely large mantissas need to be
331 // calculated, because otherwise they overflow uint64. Items from C
332 // with larger mantissa
333 {
334 {Number{1'000'000'000'000'000, -15},
335 Number{6'555'555'555'555'555, -29},
336 Number{false, 9'999'999'999'999'344'444ULL, -19, Number::Normalized{}}},
337 {Number{6'555'555'555'555'555, -29},
338 Number{1'000'000'000'000'000, -15},
339 Number{true, 9'999'999'999'999'344'444ULL, -19, Number::Normalized{}}},
340 {Number{1'000'000'000'000'000, -15}, Number{1'000'000'000'000'000, -15}, Number{0}},
341 {Number{1'000'000'000'000'000, -15},
342 Number{1'000'000'000'000'001, -15},
343 Number{-1'000'000'000'000'000, -30}},
344 {Number{1'000'000'000'000'001, -15},
345 Number{1'000'000'000'000'000, -15},
346 Number{1'000'000'000'000'000, -30}},
347 // Items from cSmall expanded for the larger mantissa
348 {Number{1'000'000'000'000'000'000, -18},
349 Number{6'555'555'555'555'555'555, -32},
350 Number{false, 9'999'999'999'999'344'444ULL, -19, Number::Normalized{}}},
351 {Number{6'555'555'555'555'555'555, -32},
352 Number{1'000'000'000'000'000'000, -18},
353 Number{true, 9'999'999'999'999'344'444ULL, -19, Number::Normalized{}}},
354 {Number{1'000'000'000'000'000'000, -18},
355 Number{1'000'000'000'000'000'000, -18},
356 Number{0}},
357 {Number{1'000'000'000'000'000'000, -18},
358 Number{1'000'000'000'000'000'001, -18},
359 Number{-1'000'000'000'000'000'000, -36}},
360 {Number{1'000'000'000'000'000'001, -18},
361 Number{1'000'000'000'000'000'000, -18},
362 Number{1'000'000'000'000'000'000, -36}},
364 {Number{false, Number::kMaxRep + 1, 0, Number::Normalized{}},
365 Number{1, 0},
366 Number{(Number::kMaxRep / 10) + 1, 1}},
367 {Number{false, Number::kMaxRep + 1, 0, Number::Normalized{}},
368 Number{3, 0},
370 {power(2, 63), Number{3, 0}, Number{Number::kMaxRep}},
371 });
372 auto test = [this](auto const& c) {
373 for (auto const& [x, y, z] : c)
374 {
375 auto const result = x - y;
377 ss << x << " - " << y << " = " << result << ". Expected: " << z;
378 BEAST_EXPECTS(result == z, ss.str());
379 }
380 };
382 {
383 test(cSmall);
384 }
385 else
386 {
387 test(cLarge);
388 }
389 }
390
391 void
393 {
394 auto const scale = Number::getMantissaScale();
395 testcase << "test_mul " << to_string(scale);
396
398 auto test = [this](auto const& c) {
399 for (auto const& [x, y, z] : c)
400 {
401 auto const result = x * y;
403 ss << x << " * " << y << " = " << result << ". Expected: " << z;
404 BEAST_EXPECTS(result == z, ss.str());
405 }
406 };
407 auto tests = [&](auto const& cSmall, auto const& cLarge) {
409 {
410 test(cSmall);
411 }
412 else
413 {
414 test(cLarge);
415 }
416 };
417 auto const maxMantissa = Number::maxMantissa();
418
420 {
421 auto const cSmall = std::to_array<Case>({
422 {Number{7}, Number{8}, Number{56}},
423 {Number{1414213562373095, -15},
424 Number{1414213562373095, -15},
425 Number{2000000000000000, -15}},
426 {Number{-1414213562373095, -15},
427 Number{1414213562373095, -15},
428 Number{-2000000000000000, -15}},
429 {Number{-1414213562373095, -15},
430 Number{-1414213562373095, -15},
431 Number{2000000000000000, -15}},
432 {Number{3214285714285706, -15},
433 Number{3111111111111119, -15},
434 Number{1000000000000000, -14}},
435 {Number{1000000000000000, -32768}, Number{1000000000000000, -32768}, Number{0}},
436 // Maximum mantissa range
437 {Number{9'999'999'999'999'999, 0},
438 Number{9'999'999'999'999'999, 0},
439 Number{9'999'999'999'999'998, 16}},
440 });
441 auto const cLarge = std::to_array<Case>({
442 // Note that items with extremely large mantissas need to be
443 // calculated, because otherwise they overflow uint64. Items
444 // from C with larger mantissa
445 {Number{7}, Number{8}, Number{56}},
446 {Number{1414213562373095, -15},
447 Number{1414213562373095, -15},
448 Number{1999999999999999862, -18}},
449 {Number{-1414213562373095, -15},
450 Number{1414213562373095, -15},
451 Number{-1999999999999999862, -18}},
452 {Number{-1414213562373095, -15},
453 Number{-1414213562373095, -15},
454 Number{1999999999999999862, -18}},
455 {Number{3214285714285706, -15},
456 Number{3111111111111119, -15},
457 Number{false, 9'999'999'999'999'999'579ULL, -18, Number::Normalized{}}},
458 {Number{1000000000000000000, -32768},
459 Number{1000000000000000000, -32768},
460 Number{0}},
461 // Items from cSmall expanded for the larger mantissa,
462 // except duplicates. Sadly, it looks like sqrt(2)^2 != 2
463 // with higher precision
464 {Number{1414213562373095049, -18},
465 Number{1414213562373095049, -18},
466 Number{2000000000000000001, -18}},
467 {Number{-1414213562373095048, -18},
468 Number{1414213562373095048, -18},
469 Number{-1999999999999999998, -18}},
470 {Number{-1414213562373095048, -18},
471 Number{-1414213562373095049, -18},
472 Number{1999999999999999999, -18}},
473 {Number{3214285714285714278, -18}, Number{3111111111111111119, -18}, Number{10, 0}},
474 // Maximum mantissa range - rounds up to 1e19
475 {Number{false, maxMantissa, 0, Number::Normalized{}},
476 Number{false, maxMantissa, 0, Number::Normalized{}},
477 Number{1, 38}},
478 // Maximum int64 range
481 Number{85'070'591'730'234'615'85, 19}},
482 });
483 tests(cSmall, cLarge);
484 }
486 testcase << "test_mul " << to_string(Number::getMantissaScale()) << " towards_zero";
487 {
488 auto const cSmall = std::to_array<Case>(
489 {{Number{7}, Number{8}, Number{56}},
490 {Number{1414213562373095, -15},
491 Number{1414213562373095, -15},
492 Number{1999999999999999, -15}},
493 {Number{-1414213562373095, -15},
494 Number{1414213562373095, -15},
495 Number{-1999999999999999, -15}},
496 {Number{-1414213562373095, -15},
497 Number{-1414213562373095, -15},
498 Number{1999999999999999, -15}},
499 {Number{3214285714285706, -15},
500 Number{3111111111111119, -15},
501 Number{9999999999999999, -15}},
502 {Number{1000000000000000, -32768}, Number{1000000000000000, -32768}, Number{0}}});
503 auto const cLarge = std::to_array<Case>(
504 // Note that items with extremely large mantissas need to be
505 // calculated, because otherwise they overflow uint64. Items
506 // from C with larger mantissa
507 {
508 {Number{7}, Number{8}, Number{56}},
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{-1414213562373095, -15},
516 Number{-1414213562373095, -15},
517 Number{1999999999999999861, -18}},
518 {Number{3214285714285706, -15},
519 Number{3111111111111119, -15},
520 Number{false, 9999999999999999579ULL, -18, Number::Normalized{}}},
521 {Number{1000000000000000000, -32768},
522 Number{1000000000000000000, -32768},
523 Number{0}},
524 // Items from cSmall expanded for the larger mantissa,
525 // except duplicates. Sadly, it looks like sqrt(2)^2 != 2
526 // with higher precision
527 {Number{1414213562373095049, -18},
528 Number{1414213562373095049, -18},
529 Number{2, 0}},
530 {Number{-1414213562373095048, -18},
531 Number{1414213562373095048, -18},
532 Number{-1999999999999999997, -18}},
533 {Number{-1414213562373095048, -18},
534 Number{-1414213562373095049, -18},
535 Number{1999999999999999999, -18}},
536 {Number{3214285714285714278, -18},
537 Number{3111111111111111119, -18},
538 Number{10, 0}},
539 // Maximum mantissa range - rounds down to maxMantissa/10e1
540 // 99'999'999'999'999'999'800'000'000'000'000'000'100
541 {Number{false, maxMantissa, 0, Number::Normalized{}},
542 Number{false, maxMantissa, 0, Number::Normalized{}},
543 Number{false, (maxMantissa / 10) - 1, 20, Number::Normalized{}}},
544 // Maximum int64 range
545 // 85'070'591'730'234'615'847'396'907'784'232'501'249
548 Number{85'070'591'730'234'615'84, 19}},
549 });
550 tests(cSmall, cLarge);
551 }
553 testcase << "test_mul " << to_string(Number::getMantissaScale()) << " downward";
554 {
555 auto const cSmall = std::to_array<Case>(
556 {{Number{7}, Number{8}, Number{56}},
557 {Number{1414213562373095, -15},
558 Number{1414213562373095, -15},
559 Number{1999999999999999, -15}},
560 {Number{-1414213562373095, -15},
561 Number{1414213562373095, -15},
562 Number{-2000000000000000, -15}},
563 {Number{-1414213562373095, -15},
564 Number{-1414213562373095, -15},
565 Number{1999999999999999, -15}},
566 {Number{3214285714285706, -15},
567 Number{3111111111111119, -15},
568 Number{9999999999999999, -15}},
569 {Number{1000000000000000, -32768}, Number{1000000000000000, -32768}, Number{0}}});
570 auto const cLarge = std::to_array<Case>(
571 // Note that items with extremely large mantissas need to be
572 // calculated, because otherwise they overflow uint64. Items
573 // from C with larger mantissa
574 {
575 {Number{7}, Number{8}, Number{56}},
576 {Number{1414213562373095, -15},
577 Number{1414213562373095, -15},
578 Number{1999999999999999861, -18}},
579 {Number{-1414213562373095, -15},
580 Number{1414213562373095, -15},
581 Number{-1999999999999999862, -18}},
582 {Number{-1414213562373095, -15},
583 Number{-1414213562373095, -15},
584 Number{1999999999999999861, -18}},
585 {Number{3214285714285706, -15},
586 Number{3111111111111119, -15},
587 Number{false, 9'999'999'999'999'999'579ULL, -18, Number::Normalized{}}},
588 {Number{1000000000000000000, -32768},
589 Number{1000000000000000000, -32768},
590 Number{0}},
591 // Items from cSmall expanded for the larger mantissa,
592 // except duplicates. Sadly, it looks like sqrt(2)^2 != 2
593 // with higher precision
594 {Number{1414213562373095049, -18},
595 Number{1414213562373095049, -18},
596 Number{2, 0}},
597 {Number{-1414213562373095048, -18},
598 Number{1414213562373095048, -18},
599 Number{-1999999999999999998, -18}},
600 {Number{-1414213562373095048, -18},
601 Number{-1414213562373095049, -18},
602 Number{1999999999999999999, -18}},
603 {Number{3214285714285714278, -18},
604 Number{3111111111111111119, -18},
605 Number{10, 0}},
606 // Maximum mantissa range - rounds down to maxMantissa/10e1
607 // 99'999'999'999'999'999'800'000'000'000'000'000'100
608 {Number{false, maxMantissa, 0, Number::Normalized{}},
609 Number{false, maxMantissa, 0, Number::Normalized{}},
610 Number{false, (maxMantissa / 10) - 1, 20, Number::Normalized{}}},
611 // Maximum int64 range
612 // 85'070'591'730'234'615'847'396'907'784'232'501'249
615 Number{85'070'591'730'234'615'84, 19}},
616 });
617 tests(cSmall, cLarge);
618 }
620 testcase << "test_mul " << to_string(Number::getMantissaScale()) << " upward";
621 {
622 auto const cSmall = std::to_array<Case>(
623 {{Number{7}, Number{8}, Number{56}},
624 {Number{1414213562373095, -15},
625 Number{1414213562373095, -15},
626 Number{2000000000000000, -15}},
627 {Number{-1414213562373095, -15},
628 Number{1414213562373095, -15},
629 Number{-1999999999999999, -15}},
630 {Number{-1414213562373095, -15},
631 Number{-1414213562373095, -15},
632 Number{2000000000000000, -15}},
633 {Number{3214285714285706, -15},
634 Number{3111111111111119, -15},
635 Number{1000000000000000, -14}},
636 {Number{1000000000000000, -32768}, Number{1000000000000000, -32768}, Number{0}}});
637 auto const cLarge = std::to_array<Case>(
638 // Note that items with extremely large mantissas need to be
639 // calculated, because otherwise they overflow uint64. Items
640 // from C with larger mantissa
641 {
642 {Number{7}, Number{8}, Number{56}},
643 {Number{1414213562373095, -15},
644 Number{1414213562373095, -15},
645 Number{1999999999999999862, -18}},
646 {Number{-1414213562373095, -15},
647 Number{1414213562373095, -15},
648 Number{-1999999999999999861, -18}},
649 {Number{-1414213562373095, -15},
650 Number{-1414213562373095, -15},
651 Number{1999999999999999862, -18}},
652 {Number{3214285714285706, -15},
653 Number{3111111111111119, -15},
654 Number{999999999999999958, -17}},
655 {Number{1000000000000000000, -32768},
656 Number{1000000000000000000, -32768},
657 Number{0}},
658 // Items from cSmall expanded for the larger mantissa,
659 // except duplicates. Sadly, it looks like sqrt(2)^2 != 2
660 // with higher precision
661 {Number{1414213562373095049, -18},
662 Number{1414213562373095049, -18},
663 Number{2000000000000000001, -18}},
664 {Number{-1414213562373095048, -18},
665 Number{1414213562373095048, -18},
666 Number{-1999999999999999997, -18}},
667 {Number{-1414213562373095048, -18},
668 Number{-1414213562373095049, -18},
669 Number{2, 0}},
670 {Number{3214285714285714278, -18},
671 Number{3111111111111111119, -18},
672 Number{1000000000000000001, -17}},
673 // Maximum mantissa range - rounds up to minMantissa*10
674 // 1e19*1e19=1e38
675 {Number{false, maxMantissa, 0, Number::Normalized{}},
676 Number{false, maxMantissa, 0, Number::Normalized{}},
677 Number{1, 38}},
678 // Maximum int64 range
679 // 85'070'591'730'234'615'847'396'907'784'232'501'249
682 Number{85'070'591'730'234'615'85, 19}},
683 });
684 tests(cSmall, cLarge);
685 }
686 testcase << "test_mul " << to_string(Number::getMantissaScale()) << " overflow";
687 {
688 bool caught = false;
689 try
690 {
691 Number{false, maxMantissa, 32768, Number::Normalized{}} *
692 Number{false, Number::minMantissa() * 5, 32767, Number::Normalized{}};
693 }
694 catch (std::overflow_error const&)
695 {
696 caught = true;
697 }
698 BEAST_EXPECT(caught);
699 }
700 }
701
702 void
704 {
705 auto const scale = Number::getMantissaScale();
706 testcase << "test_div " << to_string(scale);
707
709 auto test = [this](auto const& c) {
710 for (auto const& [x, y, z] : c)
711 {
712 auto const result = x / y;
714 ss << x << " / " << y << " = " << result << ". Expected: " << z;
715 BEAST_EXPECTS(result == z, ss.str());
716 }
717 };
718 auto const maxMantissa = Number::maxMantissa();
719 auto tests = [&](auto const& cSmall, auto const& cLarge) {
721 {
722 test(cSmall);
723 }
724 else
725 {
726 test(cLarge);
727 }
728 };
730 {
731 auto const cSmall = std::to_array<Case>(
732 {{Number{1}, Number{2}, Number{5, -1}},
733 {Number{1}, Number{10}, Number{1, -1}},
734 {Number{1}, Number{-10}, Number{-1, -1}},
735 {Number{0}, Number{100}, Number{0}},
736 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
737 {Number{9'999'999'999'999'999},
738 Number{1'000'000'000'000'000},
739 Number{9'999'999'999'999'999, -15}},
740 {Number{2}, Number{3}, Number{6'666'666'666'666'667, -16}},
741 {Number{-2}, Number{3}, Number{-6'666'666'666'666'667, -16}},
742 {Number{1}, Number{7}, Number{1'428'571'428'571'428, -16}}});
743 auto const cLarge = std::to_array<Case>(
744 // Note that items with extremely large mantissas need to be
745 // calculated, because otherwise they overflow uint64. Items
746 // from C with larger mantissa
747 {{Number{1}, Number{2}, Number{5, -1}},
748 {Number{1}, Number{10}, Number{1, -1}},
749 {Number{1}, Number{-10}, Number{-1, -1}},
750 {Number{0}, Number{100}, Number{0}},
751 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
752 {Number{9'999'999'999'999'999},
753 Number{1'000'000'000'000'000},
754 Number{9'999'999'999'999'999, -15}},
755 {Number{2}, Number{3}, Number{6'666'666'666'666'666'667, -19}},
756 {Number{-2}, Number{3}, Number{-6'666'666'666'666'666'667, -19}},
757 {Number{1}, Number{7}, Number{1'428'571'428'571'428'571, -19}},
758 // Items from cSmall expanded for the larger mantissa, except
759 // duplicates.
760 {Number{1414213562373095049, -13}, Number{1414213562373095049, -13}, Number{1}},
761 {Number{false, maxMantissa, 0, Number::Normalized{}},
762 Number{1'000'000'000'000'000'000},
763 Number{false, maxMantissa, -18, Number::Normalized{}}}});
764 tests(cSmall, cLarge);
765 }
766 testcase << "test_div " << to_string(Number::getMantissaScale()) << " towards_zero";
768 {
769 auto const cSmall = std::to_array<Case>(
770 {{Number{1}, Number{2}, Number{5, -1}},
771 {Number{1}, Number{10}, Number{1, -1}},
772 {Number{1}, Number{-10}, Number{-1, -1}},
773 {Number{0}, Number{100}, Number{0}},
774 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
775 {Number{9'999'999'999'999'999},
776 Number{1'000'000'000'000'000},
777 Number{9'999'999'999'999'999, -15}},
778 {Number{2}, Number{3}, Number{6'666'666'666'666'666, -16}},
779 {Number{-2}, Number{3}, Number{-6'666'666'666'666'666, -16}},
780 {Number{1}, Number{7}, Number{1'428'571'428'571'428, -16}}});
781 auto const cLarge = std::to_array<Case>(
782 // Note that items with extremely large mantissas need to be
783 // calculated, because otherwise they overflow uint64. Items
784 // from C with larger mantissa
785 {{Number{1}, Number{2}, Number{5, -1}},
786 {Number{1}, Number{10}, Number{1, -1}},
787 {Number{1}, Number{-10}, Number{-1, -1}},
788 {Number{0}, Number{100}, Number{0}},
789 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
790 {Number{9'999'999'999'999'999},
791 Number{1'000'000'000'000'000},
792 Number{9'999'999'999'999'999, -15}},
793 {Number{2}, Number{3}, Number{6'666'666'666'666'666'666, -19}},
794 {Number{-2}, Number{3}, Number{-6'666'666'666'666'666'666, -19}},
795 {Number{1}, Number{7}, Number{1'428'571'428'571'428'571, -19}},
796 // Items from cSmall expanded for the larger mantissa, except
797 // duplicates.
798 {Number{1414213562373095049, -13}, Number{1414213562373095049, -13}, Number{1}},
799 {Number{false, maxMantissa, 0, Number::Normalized{}},
800 Number{1'000'000'000'000'000'000},
801 Number{false, maxMantissa, -18, Number::Normalized{}}}});
802 tests(cSmall, cLarge);
803 }
804 testcase << "test_div " << to_string(Number::getMantissaScale()) << " downward";
806 {
807 auto const cSmall = std::to_array<Case>(
808 {{Number{1}, Number{2}, Number{5, -1}},
809 {Number{1}, Number{10}, Number{1, -1}},
810 {Number{1}, Number{-10}, Number{-1, -1}},
811 {Number{0}, Number{100}, Number{0}},
812 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
813 {Number{9'999'999'999'999'999},
814 Number{1'000'000'000'000'000},
815 Number{9'999'999'999'999'999, -15}},
816 {Number{2}, Number{3}, Number{6'666'666'666'666'666, -16}},
817 {Number{-2}, Number{3}, Number{-6'666'666'666'666'667, -16}},
818 {Number{1}, Number{7}, Number{1'428'571'428'571'428, -16}}});
819 auto const cLarge = std::to_array<Case>(
820 // Note that items with extremely large mantissas need to be
821 // calculated, because otherwise they overflow uint64. Items
822 // from C with larger mantissa
823 {{Number{1}, Number{2}, Number{5, -1}},
824 {Number{1}, Number{10}, Number{1, -1}},
825 {Number{1}, Number{-10}, Number{-1, -1}},
826 {Number{0}, Number{100}, Number{0}},
827 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
828 {Number{9'999'999'999'999'999},
829 Number{1'000'000'000'000'000},
830 Number{9'999'999'999'999'999, -15}},
831 {Number{2}, Number{3}, Number{6'666'666'666'666'666'666, -19}},
832 {Number{-2}, Number{3}, Number{-6'666'666'666'666'666'667, -19}},
833 {Number{1}, Number{7}, Number{1'428'571'428'571'428'571, -19}},
834 // Items from cSmall expanded for the larger mantissa, except
835 // duplicates.
836 {Number{1414213562373095049, -13}, Number{1414213562373095049, -13}, Number{1}},
837 {Number{false, maxMantissa, 0, Number::Normalized{}},
838 Number{1'000'000'000'000'000'000},
839 Number{false, maxMantissa, -18, Number::Normalized{}}}});
840 tests(cSmall, cLarge);
841 }
842 testcase << "test_div " << to_string(Number::getMantissaScale()) << " upward";
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}, Number{1414213562373095, -10}, Number{1}},
851 {Number{9'999'999'999'999'999},
852 Number{1'000'000'000'000'000},
853 Number{9'999'999'999'999'999, -15}},
854 {Number{2}, Number{3}, Number{6'666'666'666'666'667, -16}},
855 {Number{-2}, Number{3}, Number{-6'666'666'666'666'666, -16}},
856 {Number{1}, Number{7}, Number{1'428'571'428'571'429, -16}}});
857 auto const cLarge = std::to_array<Case>(
858 // Note that items with extremely large mantissas need to be
859 // calculated, because otherwise they overflow uint64. Items
860 // from C with larger mantissa
861 {{Number{1}, Number{2}, Number{5, -1}},
862 {Number{1}, Number{10}, Number{1, -1}},
863 {Number{1}, Number{-10}, Number{-1, -1}},
864 {Number{0}, Number{100}, Number{0}},
865 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
866 {Number{9'999'999'999'999'999},
867 Number{1'000'000'000'000'000},
868 Number{9'999'999'999'999'999, -15}},
869 {Number{2}, Number{3}, Number{6'666'666'666'666'666'667, -19}},
870 {Number{-2}, Number{3}, Number{-6'666'666'666'666'666'666, -19}},
871 {Number{1}, Number{7}, Number{1'428'571'428'571'428'572, -19}},
872 // Items from cSmall expanded for the larger mantissa, except
873 // duplicates.
874 {Number{1414213562373095049, -13}, Number{1414213562373095049, -13}, Number{1}},
875 {Number{false, maxMantissa, 0, Number::Normalized{}},
876 Number{1'000'000'000'000'000'000},
877 Number{false, maxMantissa, -18, Number::Normalized{}}}});
878 tests(cSmall, cLarge);
879 }
880 testcase << "test_div " << to_string(Number::getMantissaScale()) << " overflow";
881 bool caught = false;
882 try
883 {
884 Number{1000000000000000, -15} / Number{0};
885 }
886 catch (std::overflow_error const&)
887 {
888 caught = true;
889 }
890 BEAST_EXPECT(caught);
891 }
892
893 void
895 {
896 auto const scale = Number::getMantissaScale();
897 testcase << "test_root " << to_string(scale);
898
900 auto test = [this](auto const& c) {
901 for (auto const& [x, y, z] : c)
902 {
903 auto const result = root(x, y);
905 ss << "root(" << x << ", " << y << ") = " << result << ". Expected: " << z;
906 BEAST_EXPECTS(result == z, ss.str());
907 }
908 };
909 /*
910 auto tests = [&](auto const& cSmall, auto const& cLarge) {
911 test(cSmall);
912 if (scale != MantissaRange::MantissaScale::Small)
913 test(cLarge);
914 };
915 */
916
917 auto const cSmall = std::to_array<Case>(
918 {{Number{2}, 2, Number{1414213562373095049, -18}},
919 {Number{2'000'000}, 2, Number{1414213562373095049, -15}},
920 {Number{2, -30}, 2, Number{1414213562373095049, -33}},
921 {Number{-27}, 3, Number{-3}},
922 {Number{1}, 5, Number{1}},
923 {Number{-1}, 0, Number{1}},
924 {Number{5, -1}, 0, Number{0}},
925 {Number{0}, 5, Number{0}},
926 {Number{5625, -4}, 2, Number{75, -2}}});
927 auto const cLarge = std::to_array<Case>({
928 {Number{false, Number::maxMantissa() - 9, -1, Number::Normalized{}},
929 2,
930 Number{false, 999'999'999'999'999'999, -9, Number::Normalized{}}},
931 {Number{false, Number::maxMantissa() - 9, 0, Number::Normalized{}},
932 2,
933 Number{false, 3'162'277'660'168'379'330, -9, Number::Normalized{}}},
935 2,
936 Number{false, 3'037'000'499'976049692, -9, Number::Normalized{}}},
938 4,
939 Number{false, 55'108'98747006743627, -14, Number::Normalized{}}},
940 });
941 test(cSmall);
943 {
945 test(cLarge);
946 }
947 bool caught = false;
948 try
949 {
950 (void)root(Number{-2}, 0);
951 }
952 catch (std::overflow_error const&)
953 {
954 caught = true;
955 }
956 BEAST_EXPECT(caught);
957 caught = false;
958 try
959 {
960 (void)root(Number{-2}, 4);
961 }
962 catch (std::overflow_error const&)
963 {
964 caught = true;
965 }
966 BEAST_EXPECT(caught);
967 }
968
969 void
971 {
972 auto const scale = Number::getMantissaScale();
973 testcase << "test_root2 " << to_string(scale);
974
975 auto test = [this](auto const& c) {
976 for (auto const& x : c)
977 {
978 auto const expected = root(x, 2);
979 auto const result = root2(x);
981 ss << "root2(" << x << ") = " << result << ". Expected: " << expected;
982 BEAST_EXPECTS(result == expected, ss.str());
983 }
984 };
985
986 auto const cSmall = std::to_array<Number>({
987 Number{2},
988 Number{2'000'000},
989 Number{2, -30},
990 Number{27},
991 Number{1},
992 Number{5, -1},
993 Number{0},
994 Number{5625, -4},
996 });
997 test(cSmall);
998 bool caught = false;
999 try
1000 {
1001 (void)root2(Number{-2});
1002 }
1003 catch (std::overflow_error const&)
1004 {
1005 caught = true;
1006 }
1007 BEAST_EXPECT(caught);
1008 }
1009
1010 void
1012 {
1013 testcase << "test_power1 " << to_string(Number::getMantissaScale());
1015 Case const c[]{
1016 {Number{64}, 0, Number{1}},
1017 {Number{64}, 1, Number{64}},
1018 {Number{64}, 2, Number{4096}},
1019 {Number{-64}, 2, Number{4096}},
1020 {Number{64}, 3, Number{262144}},
1021 {Number{-64}, 3, Number{-262144}},
1022 {Number{64}, 11, Number{false, 7378697629483820646ULL, 1, Number::Normalized{}}},
1023 {Number{-64}, 11, Number{true, 7378697629483820646ULL, 1, Number::Normalized{}}}};
1024 for (auto const& [x, y, z] : c)
1025 BEAST_EXPECT((power(x, y) == z));
1026 }
1027
1028 void
1030 {
1031 testcase << "test_power2 " << to_string(Number::getMantissaScale());
1033 Case const c[]{
1034 {Number{1}, 3, 7, Number{1}},
1035 {Number{-1}, 1, 0, Number{1}},
1036 {Number{-1, -1}, 1, 0, Number{0}},
1037 {Number{16}, 0, 5, Number{1}},
1038 {Number{34}, 3, 3, Number{34}},
1039 {Number{4}, 3, 2, Number{8}}};
1040 for (auto const& [x, n, d, z] : c)
1041 BEAST_EXPECT((power(x, n, d) == z));
1042 bool caught = false;
1043 try
1044 {
1045 (void)power(Number{7}, 0, 0);
1046 }
1047 catch (std::overflow_error const&)
1048 {
1049 caught = true;
1050 }
1051 BEAST_EXPECT(caught);
1052 caught = false;
1053 try
1054 {
1055 (void)power(Number{7}, 1, 0);
1056 }
1057 catch (std::overflow_error const&)
1058 {
1059 caught = true;
1060 }
1061 BEAST_EXPECT(caught);
1062 caught = false;
1063 try
1064 {
1065 (void)power(Number{-1, -1}, 3, 2);
1066 }
1067 catch (std::overflow_error const&)
1068 {
1069 caught = true;
1070 }
1071 BEAST_EXPECT(caught);
1072 }
1073
1074 void
1076 {
1077 testcase << "testConversions " << to_string(Number::getMantissaScale());
1078
1079 IOUAmount const x{5, 6};
1080 Number const y = x;
1081 BEAST_EXPECT((y == Number{5, 6}));
1082 IOUAmount const z{y};
1083 BEAST_EXPECT(x == z);
1084 XRPAmount const xrp{500};
1085 STAmount const st = xrp;
1086 Number const n = st;
1087 BEAST_EXPECT(XRPAmount{n} == xrp);
1088 IOUAmount const x0{0, 0};
1089 Number const y0 = x0;
1090 BEAST_EXPECT((y0 == Number{0}));
1091 IOUAmount const z0{y0};
1092 BEAST_EXPECT(x0 == z0);
1093 XRPAmount const xrp0{0};
1094 Number const n0 = xrp0;
1095 BEAST_EXPECT(n0 == Number{0});
1096 XRPAmount const xrp1{n0};
1097 BEAST_EXPECT(xrp1 == xrp0);
1098 }
1099
1100 void
1102 {
1103 testcase << "test_to_integer " << to_string(Number::getMantissaScale());
1106 {
1107 Case const c[]{
1108 {Number{0}, 0},
1109 {Number{1}, 1},
1110 {Number{2}, 2},
1111 {Number{3}, 3},
1112 {Number{-1}, -1},
1113 {Number{-2}, -2},
1114 {Number{-3}, -3},
1115 {Number{10}, 10},
1116 {Number{99}, 99},
1117 {Number{1155}, 1155},
1118 {Number{9'999'999'999'999'999, 0}, 9'999'999'999'999'999},
1119 {Number{9'999'999'999'999'999, 1}, 99'999'999'999'999'990},
1120 {Number{9'999'999'999'999'999, 2}, 999'999'999'999'999'900},
1121 {Number{-9'999'999'999'999'999, 2}, -999'999'999'999'999'900},
1122 {Number{15, -1}, 2},
1123 {Number{14, -1}, 1},
1124 {Number{16, -1}, 2},
1125 {Number{25, -1}, 2},
1126 {Number{6, -1}, 1},
1127 {Number{5, -1}, 0},
1128 {Number{4, -1}, 0},
1129 {Number{-15, -1}, -2},
1130 {Number{-14, -1}, -1},
1131 {Number{-16, -1}, -2},
1132 {Number{-25, -1}, -2},
1133 {Number{-6, -1}, -1},
1134 {Number{-5, -1}, 0},
1135 {Number{-4, -1}, 0}};
1136 for (auto const& [x, y] : c)
1137 {
1138 auto j = static_cast<std::int64_t>(x);
1139 BEAST_EXPECT(j == y);
1140 }
1141 }
1143 BEAST_EXPECT(prevMode == Number::RoundingMode::ToNearest);
1144 {
1145 Case const c[]{
1146 {Number{0}, 0},
1147 {Number{1}, 1},
1148 {Number{2}, 2},
1149 {Number{3}, 3},
1150 {Number{-1}, -1},
1151 {Number{-2}, -2},
1152 {Number{-3}, -3},
1153 {Number{10}, 10},
1154 {Number{99}, 99},
1155 {Number{1155}, 1155},
1156 {Number{9'999'999'999'999'999, 0}, 9'999'999'999'999'999},
1157 {Number{9'999'999'999'999'999, 1}, 99'999'999'999'999'990},
1158 {Number{9'999'999'999'999'999, 2}, 999'999'999'999'999'900},
1159 {Number{-9'999'999'999'999'999, 2}, -999'999'999'999'999'900},
1160 {Number{15, -1}, 1},
1161 {Number{14, -1}, 1},
1162 {Number{16, -1}, 1},
1163 {Number{25, -1}, 2},
1164 {Number{6, -1}, 0},
1165 {Number{5, -1}, 0},
1166 {Number{4, -1}, 0},
1167 {Number{-15, -1}, -1},
1168 {Number{-14, -1}, -1},
1169 {Number{-16, -1}, -1},
1170 {Number{-25, -1}, -2},
1171 {Number{-6, -1}, 0},
1172 {Number{-5, -1}, 0},
1173 {Number{-4, -1}, 0}};
1174 for (auto const& [x, y] : c)
1175 {
1176 auto j = static_cast<std::int64_t>(x);
1177 BEAST_EXPECT(j == y);
1178 }
1179 }
1181 BEAST_EXPECT(prevMode == Number::RoundingMode::TowardsZero);
1182 {
1183 Case const c[]{
1184 {Number{0}, 0},
1185 {Number{1}, 1},
1186 {Number{2}, 2},
1187 {Number{3}, 3},
1188 {Number{-1}, -1},
1189 {Number{-2}, -2},
1190 {Number{-3}, -3},
1191 {Number{10}, 10},
1192 {Number{99}, 99},
1193 {Number{1155}, 1155},
1194 {Number{9'999'999'999'999'999, 0}, 9'999'999'999'999'999},
1195 {Number{9'999'999'999'999'999, 1}, 99'999'999'999'999'990},
1196 {Number{9'999'999'999'999'999, 2}, 999'999'999'999'999'900},
1197 {Number{-9'999'999'999'999'999, 2}, -999'999'999'999'999'900},
1198 {Number{15, -1}, 1},
1199 {Number{14, -1}, 1},
1200 {Number{16, -1}, 1},
1201 {Number{25, -1}, 2},
1202 {Number{6, -1}, 0},
1203 {Number{5, -1}, 0},
1204 {Number{4, -1}, 0},
1205 {Number{-15, -1}, -2},
1206 {Number{-14, -1}, -2},
1207 {Number{-16, -1}, -2},
1208 {Number{-25, -1}, -3},
1209 {Number{-6, -1}, -1},
1210 {Number{-5, -1}, -1},
1211 {Number{-4, -1}, -1}};
1212 for (auto const& [x, y] : c)
1213 {
1214 auto j = static_cast<std::int64_t>(x);
1215 BEAST_EXPECT(j == y);
1216 }
1217 }
1219 BEAST_EXPECT(prevMode == Number::RoundingMode::Downward);
1220 {
1221 Case const c[]{
1222 {Number{0}, 0},
1223 {Number{1}, 1},
1224 {Number{2}, 2},
1225 {Number{3}, 3},
1226 {Number{-1}, -1},
1227 {Number{-2}, -2},
1228 {Number{-3}, -3},
1229 {Number{10}, 10},
1230 {Number{99}, 99},
1231 {Number{1155}, 1155},
1232 {Number{9'999'999'999'999'999, 0}, 9'999'999'999'999'999},
1233 {Number{9'999'999'999'999'999, 1}, 99'999'999'999'999'990},
1234 {Number{9'999'999'999'999'999, 2}, 999'999'999'999'999'900},
1235 {Number{-9'999'999'999'999'999, 2}, -999'999'999'999'999'900},
1236 {Number{15, -1}, 2},
1237 {Number{14, -1}, 2},
1238 {Number{16, -1}, 2},
1239 {Number{25, -1}, 3},
1240 {Number{6, -1}, 1},
1241 {Number{5, -1}, 1},
1242 {Number{4, -1}, 1},
1243 {Number{-15, -1}, -1},
1244 {Number{-14, -1}, -1},
1245 {Number{-16, -1}, -1},
1246 {Number{-25, -1}, -2},
1247 {Number{-6, -1}, 0},
1248 {Number{-5, -1}, 0},
1249 {Number{-4, -1}, 0}};
1250 for (auto const& [x, y] : c)
1251 {
1252 auto j = static_cast<std::int64_t>(x);
1253 BEAST_EXPECT(j == y);
1254 }
1255 }
1256 bool caught = false;
1257 try
1258 {
1259 (void)static_cast<std::int64_t>(Number{9223372036854776, 3});
1260 }
1261 catch (std::overflow_error const&)
1262 {
1263 caught = true;
1264 }
1265 BEAST_EXPECT(caught);
1266 }
1267
1268 void
1270 {
1271 testcase << "test_squelch " << to_string(Number::getMantissaScale());
1272 Number const limit{1, -6};
1273 BEAST_EXPECT((squelch(Number{2, -6}, limit) == Number{2, -6}));
1274 BEAST_EXPECT((squelch(Number{1, -6}, limit) == Number{1, -6}));
1275 BEAST_EXPECT((squelch(Number{9, -7}, limit) == Number{0}));
1276 BEAST_EXPECT((squelch(Number{-2, -6}, limit) == Number{-2, -6}));
1277 BEAST_EXPECT((squelch(Number{-1, -6}, limit) == Number{-1, -6}));
1278 BEAST_EXPECT((squelch(Number{-9, -7}, limit) == Number{0}));
1279 }
1280
1281 void
1283 {
1284 auto const scale = Number::getMantissaScale();
1285 testcase << "testToString " << to_string(scale);
1286
1287 auto test = [this](Number const& n, std::string const& expected) {
1288 auto const result = to_string(n);
1290 ss << "to_string(" << result << "). Expected: " << expected;
1291 BEAST_EXPECTS(result == expected, ss.str());
1292 };
1293
1294 test(Number(-2, 0), "-2");
1295 test(Number(0, 0), "0");
1296 test(Number(2, 0), "2");
1297 test(Number(25, -3), "0.025");
1298 test(Number(-25, -3), "-0.025");
1299 test(Number(25, 1), "250");
1300 test(Number(-25, 1), "-250");
1301 test(Number(2, 20), "2e20");
1302 test(Number(-2, -20), "-2e-20");
1303 // Test the edges
1304 // ((exponent < -(25)) || (exponent > -(5)))))
1305 // or ((exponent < -(28)) || (exponent > -(8)))))
1306 test(Number(2, -10), "0.0000000002");
1307 test(Number(2, -11), "2e-11");
1308
1309 test(Number(-2, 10), "-20000000000");
1310 test(Number(-2, 11), "-2e11");
1311
1312 switch (scale)
1313 {
1315
1316 test(Number::min(), "1e-32753");
1317 test(Number::max(), "9999999999999999e32768");
1318 test(Number::lowest(), "-9999999999999999e32768");
1319 {
1321
1322 auto const maxMantissa = Number::maxMantissa();
1323 BEAST_EXPECT(maxMantissa == 9'999'999'999'999'999);
1324 test(
1325 Number{false, (maxMantissa * 1000) + 999, -3, Number::Normalized()},
1326 "9999999999999999");
1327 test(
1328 Number{true, (maxMantissa * 1000) + 999, -3, Number::Normalized()},
1329 "-9999999999999999");
1330
1331 test(Number{std::numeric_limits<std::int64_t>::max(), -3}, "9223372036854775");
1332 test(
1334 "-9223372036854775");
1335
1336 test(
1337 Number{std::numeric_limits<std::int64_t>::min(), 0}, "-9223372036854775e3");
1338 test(
1340 "9223372036854775e3");
1341 }
1342 break;
1345 // Test the edges
1346 // ((exponent < -(28)) || (exponent > -(8)))))
1347 test(Number::min(), "1e-32750");
1348 test(Number::max(), "9223372036854775807e32768");
1349 test(Number::lowest(), "-9223372036854775807e32768");
1350 {
1352
1353 auto const maxMantissa = Number::maxMantissa();
1354 BEAST_EXPECT(maxMantissa == 9'999'999'999'999'999'999ULL);
1355 test(
1356 Number{false, maxMantissa, 0, Number::Normalized{}}, "9999999999999999990");
1357 test(
1358 Number{true, maxMantissa, 0, Number::Normalized{}}, "-9999999999999999990");
1359
1360 test(
1361 Number{std::numeric_limits<std::int64_t>::max(), 0}, "9223372036854775807");
1362 test(
1364 "-9223372036854775807");
1365
1366 // Because the absolute value of min is larger than max, it
1367 // will be scaled down to fit under max. Since we're
1368 // rounding towards zero, the 8 at the end is dropped.
1369 test(
1371 "-9223372036854775800");
1372 test(
1374 "9223372036854775800");
1375 }
1376
1377 test(
1378 Number{std::numeric_limits<std::int64_t>::max(), 0} + 1, "9223372036854775810");
1379 test(
1381 "-9223372036854775810");
1382 break;
1383 default:
1384 BEAST_EXPECT(false);
1385 }
1386 }
1387
1388 void
1390 {
1391 testcase << "test_relationals " << to_string(Number::getMantissaScale());
1392
1393 {
1394 auto test = [this](auto const& nums) {
1395 BEAST_EXPECT(std::ranges::is_sorted(nums));
1396
1397 for (auto iter1 = nums.begin(); iter1 != nums.end(); ++iter1)
1398 {
1399 auto iter2 = iter1;
1400 for (++iter2; iter2 != nums.end(); ++iter2)
1401 {
1402 Number const& smaller = *iter1;
1403 Number const& larger = *iter2;
1405 ss << smaller << " < " << larger;
1406 auto const str = ss.str();
1407
1408 // The ==/!= operators use a completely different code path than <, etc.
1409 // This helps detect a breakage in one but not the other. It also helps
1410 // verify that the values are being ordered correctly.
1411 BEAST_EXPECTS(smaller != larger, str + " (!=)");
1412 BEAST_EXPECTS(!(smaller == larger), str + " (==)");
1413
1414 // true results using operator< and derived operators
1415 BEAST_EXPECTS(smaller < larger, str + " (<)");
1416 BEAST_EXPECTS(larger > smaller, str + " (>)");
1417 BEAST_EXPECTS(larger >= smaller, str + " (>=)");
1418 BEAST_EXPECTS(smaller <= larger, str + " (<=)");
1419
1420 // false results using operator< and derived operators
1421 BEAST_EXPECTS(!(larger < smaller), str + " (! <)");
1422 BEAST_EXPECTS(!(smaller > larger), str + " (! >)");
1423 BEAST_EXPECTS(!(smaller >= larger), str + " (! >=)");
1424 BEAST_EXPECTS(!(larger <= smaller), str + " (! <=)");
1425 }
1426 }
1427 };
1428
1429 auto const intNums = [this]() {
1430 // Inequality test cases are built from a list of sorted integers
1431 auto const values =
1432 std::to_array<int>({-100, -50, -20, -10, -1, 0, 1, 10, 20, 50, 100});
1433 // Check this list is sorted before converting it to Numbers.
1434 // That way if any of the other tests fail, we know it's because of code and not the
1435 // source data.
1436 BEAST_EXPECT(std::ranges::is_sorted(values));
1437
1438 std::vector<Number> result;
1439 result.reserve(values.size());
1440 for (auto const v : values)
1441 result.emplace_back(v);
1442 return result;
1443 }();
1444
1445 auto const otherNums = std::to_array<Number>({
1446 Number{-5, 100},
1447 Number{-1, 100},
1448 Number{-7, -10},
1449 Number{-2, -10},
1450 Number{0},
1451 Number{2, -10},
1452 Number{7, -10},
1453 Number{1, 100},
1454 Number{5, 100},
1455 });
1456
1457 test(intNums);
1458 test(otherNums);
1459 }
1460
1461 {
1462 // Equality test cases are <Number, __LINE__>. Number will be compared against itself
1463 using Case = std::pair<Number, int>;
1464 auto const c = std::to_array<Case>({
1465 {700, __LINE__},
1466 {50, __LINE__},
1467 {1, __LINE__},
1468 {0, __LINE__},
1469 {-1, __LINE__},
1470 {-30, __LINE__},
1471 {-600, __LINE__},
1472 });
1473 for (auto const& [n, line] : c)
1474 {
1475 auto const str = to_string(n);
1476
1477 // NOLINTBEGIN(misc-redundant-expression) Explicitly testing operators with
1478 // equivalent values
1479 expect(n == n, str + " ==", __FILE__, line);
1480 expect(!(n != n), str + " !=", __FILE__, line);
1481
1482 expect(!(n < n), str + " < ", __FILE__, line);
1483 expect(!(n > n), str + " >", __FILE__, line);
1484 expect(n >= n, str + " >=", __FILE__, line);
1485 expect(n <= n, str + " <=", __FILE__, line);
1486 // NOLINTEND(misc-redundant-expression)
1487 }
1488 }
1489 }
1490
1491 void
1493 {
1494 testcase << "test_stream " << to_string(Number::getMantissaScale());
1495 Number const x{100};
1497 os << x;
1498 BEAST_EXPECT(os.str() == to_string(x));
1499 }
1500
1501 void
1503 {
1504 testcase << "test_inc_dec " << to_string(Number::getMantissaScale());
1505 Number x{100};
1506 Number const y = +x;
1507 BEAST_EXPECT(x == y);
1508 BEAST_EXPECT(x++ == y);
1509 BEAST_EXPECT(x == Number{101});
1510 BEAST_EXPECT(x-- == Number{101});
1511 BEAST_EXPECT(x == y);
1512 }
1513
1514 void
1516 {
1517 Issue const issue;
1518 Number const n{7'518'783'80596, -5};
1520 auto res2 = STAmount{issue, n};
1521 BEAST_EXPECT(res2 == STAmount{7518784});
1522
1524 res2 = STAmount{issue, n};
1525 BEAST_EXPECT(res2 == STAmount{7518783});
1526
1528 res2 = STAmount{issue, n};
1529 BEAST_EXPECT(res2 == STAmount{7518783});
1530
1532 res2 = STAmount{issue, n};
1533 BEAST_EXPECT(res2 == STAmount{7518784});
1534 }
1535
1536 void
1538 {
1539 BEAST_EXPECT(Number(25, +1).truncate() == Number(250, 0));
1540 BEAST_EXPECT(Number(25, 0).truncate() == Number(25, 0));
1541 BEAST_EXPECT(Number(25, -1).truncate() == Number(2, 0));
1542 BEAST_EXPECT(Number(25, -2).truncate() == Number(0, 0));
1543 BEAST_EXPECT(Number(99, -2).truncate() == Number(0, 0));
1544
1545 BEAST_EXPECT(Number(-25, +1).truncate() == Number(-250, 0));
1546 BEAST_EXPECT(Number(-25, 0).truncate() == Number(-25, 0));
1547 BEAST_EXPECT(Number(-25, -1).truncate() == Number(-2, 0));
1548 BEAST_EXPECT(Number(-25, -2).truncate() == Number(0, 0));
1549 BEAST_EXPECT(Number(-99, -2).truncate() == Number(0, 0));
1550
1551 BEAST_EXPECT(Number(0, 0).truncate() == Number(0, 0));
1552 BEAST_EXPECT(Number(0, 30000).truncate() == Number(0, 0));
1553 BEAST_EXPECT(Number(0, -30000).truncate() == Number(0, 0));
1554 BEAST_EXPECT(Number(100, -30000).truncate() == Number(0, 0));
1555 BEAST_EXPECT(Number(100, -30000).truncate() == Number(0, 0));
1556 BEAST_EXPECT(Number(-100, -30000).truncate() == Number(0, 0));
1557 BEAST_EXPECT(Number(-100, -30000).truncate() == Number(0, 0));
1558 }
1559
1560 void
1562 {
1563 // Test that rounding works as expected.
1564 testcase("Rounding");
1565
1566 using NumberRoundings = std::map<Number::RoundingMode, std::int64_t>;
1567
1568 std::map<Number, NumberRoundings> const expected{
1569 // Positive numbers
1570 {Number{13, -1},
1575 {Number{23, -1},
1580 {Number{15, -1},
1585 {Number{25, -1},
1590 {Number{152, -2},
1595 {Number{252, -2},
1600 {Number{17, -1},
1605 {Number{27, -1},
1610
1611 // Negative numbers
1612 {Number{-13, -1},
1617 {Number{-23, -1},
1622 {Number{-15, -1},
1627 {Number{-25, -1},
1632 {Number{-152, -2},
1637 {Number{-252, -2},
1642 {Number{-17, -1},
1647 {Number{-27, -1},
1652 };
1653
1654 for (auto const& [num, roundings] : expected)
1655 {
1656 for (auto const& [mode, val] : roundings)
1657 {
1658 NumberRoundModeGuard const g{mode};
1659 auto const res = static_cast<std::int64_t>(num);
1660 BEAST_EXPECTS(
1661 res == val,
1662 to_string(num) + " with mode " + std::to_string(static_cast<int>(mode)) +
1663 " expected " + std::to_string(val) + " got " + std::to_string(res));
1664 }
1665 }
1666 }
1667
1668 void
1670 {
1671 auto const scale = Number::getMantissaScale();
1672 testcase << "std::int64_t " << to_string(scale);
1673
1674 // Control case
1675 BEAST_EXPECT(Number::maxMantissa() > 10);
1676 Number const ten{10};
1677 BEAST_EXPECT(ten.exponent() <= 0);
1678
1680 {
1681 BEAST_EXPECT(std::numeric_limits<std::int64_t>::max() > kInitialXrp.drops());
1682 BEAST_EXPECT(Number::maxMantissa() < kInitialXrp.drops());
1683 Number const initalXrp{kInitialXrp};
1684 BEAST_EXPECT(initalXrp.exponent() > 0);
1685
1686 Number const maxInt64{Number::kMaxRep};
1687 BEAST_EXPECT(maxInt64.exponent() > 0);
1688 // 85'070'591'730'234'615'865'843'651'857'942'052'864 - 38 digits
1689 BEAST_EXPECT((power(maxInt64, 2) == Number{85'070'591'730'234'62, 22}));
1690
1691 Number const max = Number{false, Number::maxMantissa(), 0, Number::Normalized{}};
1692 BEAST_EXPECT(max.exponent() <= 0);
1693 // 99'999'999'999'999'980'000'000'000'000'001 - 32 digits
1694 BEAST_EXPECT((power(max, 2) == Number{99'999'999'999'999'98, 16}));
1695 }
1696 else
1697 {
1698 BEAST_EXPECT(std::numeric_limits<std::int64_t>::max() > kInitialXrp.drops());
1699 BEAST_EXPECT(Number::maxMantissa() > kInitialXrp.drops());
1700 Number const initalXrp{kInitialXrp};
1701 BEAST_EXPECT(initalXrp.exponent() <= 0);
1702
1703 Number const maxInt64{Number::kMaxRep};
1704 BEAST_EXPECT(maxInt64.exponent() <= 0);
1705 // 85'070'591'730'234'615'847'396'907'784'232'501'249 - 38 digits
1706 BEAST_EXPECT((power(maxInt64, 2) == Number{85'070'591'730'234'615'85, 19}));
1707
1709
1710 auto const maxMantissa = Number::maxMantissa();
1711 Number const max = Number{false, maxMantissa, 0, Number::Normalized{}};
1712 BEAST_EXPECT(max.mantissa() == maxMantissa / 10);
1713 BEAST_EXPECT(max.exponent() == 1);
1714 // 99'999'999'999'999'999'800'000'000'000'000'000'100 - also 38
1715 // digits
1716 BEAST_EXPECT(
1717 (power(max, 2) == Number{false, (maxMantissa / 10) - 1, 20, Number::Normalized{}}));
1718 }
1719 }
1720
1721 void
1723 {
1724 auto const scale = Number::getMantissaScale();
1725 {
1726 testcase << "upward rounding produces a value below exact at kMaxRep cusp "
1727 << to_string(scale);
1728
1730
1731 constexpr std::int64_t kAValue = 1'000'000'000'000'049'863LL;
1732 constexpr std::int64_t kBValue = 9'223'372'036'854'315'903LL;
1733
1734 Number const a = kAValue;
1735 Number const b = kBValue;
1736 Number const product = a * b;
1737
1738 // Exact reference in BigInt.
1739 BigInt const exactProduct = BigInt(kAValue) * BigInt(kBValue);
1740
1741 // What Number actually stored.
1742 BigInt storedValue = BigInt(product.mantissa());
1743 for (int i = 0; i < product.exponent(); ++i)
1744 storedValue *= 10;
1745
1746 BigInt const signedDifference = storedValue - exactProduct;
1747
1748 log << "\n"
1749 << " a = " << fmt(BigInt(kAValue)) << "\n"
1750 << " b = " << fmt(BigInt(kBValue)) << "\n"
1751 << " exact a*b = " << fmt(exactProduct) << "\n"
1752 << " stored = " << fmt(storedValue) << "\n"
1753 << " stored - exact = " << fmt(signedDifference) << "\n"
1754 << " upward = " << (signedDifference >= 0 ? "held" : "VIOLATED") << "\n"
1755 << " stored.mantissa = " << product.mantissa() << "\n"
1756 << " stored.exponent = " << product.exponent() << "\n";
1757 log.flush();
1758
1759 switch (scale)
1760 {
1762 BEAST_EXPECT(signedDifference >= 0);
1763 BEAST_EXPECT(signedDifference < pow10<BigInt>(product.exponent()));
1764 BEAST_EXPECT(
1765 product.mantissa() == (std::numeric_limits<std::int64_t>::max() / 10) + 1);
1766 BEAST_EXPECT(product.exponent() == 19);
1767 break;
1768
1770 BEAST_EXPECT(signedDifference < 0);
1771 BEAST_EXPECT(
1772 product.mantissa() ==
1774 BEAST_EXPECT(product.exponent() == 18);
1775 break;
1776
1778 // The seemingly weird rounding here is because
1779 // a & b are both normalized, and both round up when
1780 // being converted to Number, so you're really
1781 // getting 1_000_000_000_000_050 * 9_223_372_036_854_316
1782 BEAST_EXPECT(signedDifference >= 0);
1783 BEAST_EXPECT(
1784 product.mantissa() ==
1786 BEAST_EXPECT(product.exponent() == 21);
1787 break;
1788 }
1789 }
1790
1791 {
1792 /* Companion regression for the kMaxRep cusp behavior, but for
1793 * `operator/=` on the cusp-fix-ENABLED `Large` scale.
1794 *
1795 * Before the dropped-remainder fix, `operator/=` with Upward
1796 * rounding could return a value STRICTLY LESS than the exact quotient,
1797 * violating Upward's directional invariant.
1798 *
1799 * Mechanism (fix-enabled path):
1800 * 1. `operator/=` computes `numerator = nm * 10^17` and
1801 * `zm = numerator / dm` (integer division, truncates remainder).
1802 * 2. If `remainder != 0`, the correction block runs:
1803 * zm *= 100000
1804 * correction = (remainder * 100000) / dm // also truncates
1805 * zm += correction
1806 * ze -= 5
1807 * The truncation in `correction` discards a sub-1/100000 residual.
1808 * 3. `normalize`'s shift loop reduces zm to fit, but the discarded
1809 * residual is BELOW the Guard's visibility, so the Guard sees fraction = 0.
1810 * 4. Under Upward + positive, `round()` returns -1 (no round-up), and
1811 * the algorithm returns the truncated zm
1812 */
1813 testcase << "operator/= Upward on Large returns value < truth " << to_string(scale);
1814
1816
1817 constexpr std::int64_t aValue = 2LL;
1818 constexpr std::int64_t bValue = 1'000'000'000'000'000'007LL;
1819 // bValue = 10^18 + 7 (prime, in [minMantissa, kMaxRep]).
1820
1821 Number const a{aValue, 0};
1822 Number const b{bValue, 0};
1823 Number const quotient = a / b;
1824
1825 dec const exact = dec(aValue) / dec(bValue);
1826 dec const stored = dec(quotient.mantissa()) * pow10(quotient.exponent());
1827 dec const diff = stored - exact;
1828
1829 log << "\n"
1830 << " a = " << aValue << "\n"
1831 << " b = " << bValue << "\n"
1832 << " exact a/b = " << fmt(exact) << "\n"
1833 << " stored a/b = " << fmt(stored) << "\n"
1834 << " stored - exact = " << fmt(diff)
1835 << " (negative => Upward gave value BELOW truth)\n"
1836 << " quotient.mantissa = " << quotient.mantissa() << "\n"
1837 << " quotient.exponent = " << quotient.exponent() << "\n";
1838 log.flush();
1839
1840 // Upward invariant: stored >= exact. Bug: stored < exact.
1841 switch (scale)
1842 {
1844 BEAST_EXPECT(stored >= exact);
1845 BEAST_EXPECT(diff < pow10(quotient.exponent()));
1846 break;
1847
1849 BEAST_EXPECT(stored < exact);
1850 BEAST_EXPECT(diff >= -pow10(quotient.exponent()));
1851 break;
1852
1854 // Small mantissa doesn't have the correction for
1855 // dropped remainders
1856 BEAST_EXPECT(stored < exact);
1857 break;
1858 }
1859 }
1860 {
1861 /* Companion test case for Upward positive operator/=: Downward negative
1862 */
1863 testcase << "operator/= Downward on Large returns value < truth " << to_string(scale);
1864
1866
1867 constexpr std::int64_t aValue = -2LL;
1868 constexpr std::int64_t bValue = 1'000'000'000'000'000'007LL;
1869 // bValue = 10^18 + 7 (prime, in [minMantissa, kMaxRep]).
1870
1871 Number const a{aValue, 0};
1872 Number const b{bValue, 0};
1873 Number const quotient = a / b;
1874
1875 dec const exact = dec(aValue) / dec(bValue);
1876 dec const stored = dec(quotient.mantissa()) * pow10(quotient.exponent());
1877 dec const diff = stored - exact;
1878
1879 log << "\n"
1880 << " a = " << aValue << "\n"
1881 << " b = " << bValue << "\n"
1882 << " exact a/b = " << fmt(exact) << "\n"
1883 << " stored a/b = " << fmt(stored) << "\n"
1884 << " stored - exact = " << fmt(diff)
1885 << " (positive => Downward gave value ABOVE truth)\n"
1886 << " quotient.mantissa = " << quotient.mantissa() << "\n"
1887 << " quotient.exponent = " << quotient.exponent() << "\n";
1888 log.flush();
1889
1890 // invariant: stored <= exact. Bug: stored > exact.
1891 switch (scale)
1892 {
1894 BEAST_EXPECT(stored <= exact);
1895 BEAST_EXPECT(diff > -pow10(quotient.exponent()));
1896 break;
1897
1899 BEAST_EXPECT(stored > exact);
1900 BEAST_EXPECT(diff <= pow10(quotient.exponent()));
1901 break;
1902
1904 // Small mantissa doesn't have the correction for
1905 // dropped remainders
1906 BEAST_EXPECT(stored < exact);
1907 break;
1908 }
1909 }
1910 {
1911 /* Companion test case for Upward positive operator/=: ToNearest
1912 *
1913 * With ToNearest, if the dropped digits are exactly "5", then the mantissa will be
1914 * rounded to even. The numbers below result in a value where the unrounded mantissa
1915 * ends in an even digit, and "infinite precision" would drop
1916 * "500000000000000000145...", but doNormalize only sees "5". Without the rounding fix,
1917 * doNormalize rounds down to the even value. With the rounding fix, doNormalize knows
1918 * there are more digits beyond "5", and so rounds _up_ to the odd value.
1919 */
1920 testcase << "operator/= ToNearest on Large returns value < truth " << to_string(scale);
1921
1923
1924 constexpr std::int64_t aValue = 1'269'917'268'816'087'809LL;
1925 constexpr std::int64_t bValue = 3'458'525'013'821'685'511LL;
1926 // bValue = 10^18 + 7 (prime, in [minMantissa, kMaxRep]).
1927
1928 Number const a{aValue, 0};
1929 Number const b{bValue, 0};
1930 Number const quotient = a / b;
1931
1932 dec const exact = dec(aValue) / dec(bValue);
1933 dec const stored = dec(quotient.mantissa()) * pow10(quotient.exponent());
1934 dec const diff = stored - exact;
1935
1936 log << "\n"
1937 << " a = " << aValue << "\n"
1938 << " b = " << bValue << "\n"
1939 << " exact a/b = " << fmt(exact) << "\n"
1940 << " stored a/b = " << fmt(stored) << "\n"
1941 << " stored - exact = " << fmt(diff)
1942 << " (negative => ToNearest gave value BELOW truth)\n"
1943 << " quotient.mantissa = " << quotient.mantissa() << "\n"
1944 << " quotient.exponent = " << quotient.exponent() << "\n";
1945 log.flush();
1946
1947 // invariant: stored >= exact. Bug: stored < exact.
1948 switch (scale)
1949 {
1951 BEAST_EXPECT(stored >= exact);
1952 BEAST_EXPECT(diff < pow10(quotient.exponent()));
1953 break;
1954
1956 BEAST_EXPECT(stored < exact);
1957 BEAST_EXPECT(diff >= -pow10(quotient.exponent()));
1958 break;
1959
1961 // Small mantissa doesn't have the correction for
1962 // dropped remainders
1963 BEAST_EXPECT(stored < exact);
1964 break;
1965 }
1966 }
1967 }
1968
1969 void
1970 run() override
1971 {
1972 for (auto const scale : MantissaRange::getAllScales())
1973 {
1975 testZero();
1976 testLimits();
1977 testToString();
1978 testAdd();
1979 testSub();
1980 testMul();
1981 testDiv();
1982 testRoot();
1983 testRoot2();
1984 testPower1();
1985 testPower2();
1987 testToInteger();
1988 testSquelch();
1990 testStream();
1991 testIncDec();
1993 testTruncate();
1994 testRounding();
1995 testInt64();
1996
1998 }
1999 }
2000};
2001
2003
2004} // namespace xrpl
T begin(T... args)
A testsuite class.
Definition suite.h:50
bool expect(Condition const &shouldBeTrue)
Evaluate a test condition.
Definition suite.h:223
LogOs< char > log
Logging output stream.
Definition suite.h:146
TestcaseT testcase
Memberspace for declaring test cases.
Definition suite.h:149
Floating point representation of amounts with high dynamic range.
Definition IOUAmount.h:24
A currency issued by an account.
Definition Issue.h:13
Sets the new scale and restores the old scale when it leaves scope.
Definition Number.h:920
boost::multiprecision::cpp_int BigInt
static T pow10(int n)
static std::string fmt(BigInt const &value)
boost::multiprecision::cpp_dec_float_50 dec
static std::string fmt(dec const &v)
void run() override
Runs the suite.
Number is a floating point type that can represent a wide range of values.
Definition Number.h:306
static internalrep minMantissa()
Definition Number.h:516
constexpr rep mantissa() const noexcept
Returns the mantissa of the external view of the Number.
Definition Number.h:640
static RoundingMode setround(RoundingMode inMode)
Definition Number.cpp:111
static Number max() noexcept
Definition Number.h:766
static constexpr internalrep kMaxRep
Definition Number.h:319
static MantissaRange::MantissaScale getMantissaScale()
Returns which mantissa scale is currently in use for normalization.
Definition Number.cpp:117
static internalrep maxMantissa()
Definition Number.h:522
constexpr int exponent() const noexcept
Returns the exponent of the external view of the Number.
Definition Number.h:661
static Number min() noexcept
Definition Number.h:760
static Number lowest() noexcept
Definition Number.h:772
static int mantissaLog()
Definition Number.h:528
T emplace_back(T... args)
T insert(T... args)
T is_sorted(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
int scale(Number const &number, Asset const &asset)
Get the scale of a Number for a given asset.
Definition STAmount.h:779
Number root(Number f, unsigned d)
Definition Number.cpp:1201
Number power(Number const &f, unsigned n)
Definition Number.cpp:1178
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:633
Number root2(Number f)
Definition Number.cpp:1275
constexpr Number squelch(Number const &x, Number const &limit) noexcept
Definition Number.h:854
constexpr XRPAmount kInitialXrp
Configure the native currency.
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, xrpl)
T reserve(T... args)
T setprecision(T... args)
T str(T... args)
static std::set< MantissaScale > const & getAllScales()
Definition Number.cpp:37
T to_string(T... args)