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