rippled
Loading...
Searching...
No Matches
Number_test.cpp
1#include <xrpl/basics/Number.h>
2#include <xrpl/beast/unit_test.h>
3#include <xrpl/protocol/IOUAmount.h>
4#include <xrpl/protocol/STAmount.h>
5#include <xrpl/protocol/SystemParameters.h>
6
7#include <sstream>
8#include <tuple>
9
10namespace xrpl {
11
13{
14public:
15 void
17 {
19
20 for (Number const& z : {Number{0, 0}, Number{0}})
21 {
22 BEAST_EXPECT(z.mantissa() == 0);
23 BEAST_EXPECT(z.exponent() == Number{}.exponent());
24
25 BEAST_EXPECT((z + z) == z);
26 BEAST_EXPECT((z - z) == z);
27 BEAST_EXPECT(z == -z);
28 }
29 }
30
31 void
33 {
34 auto const scale = Number::getMantissaScale();
35 testcase << "test_limits " << to_string(scale);
36 bool caught = false;
37 auto const minMantissa = Number::minMantissa();
38 try
39 {
40 Number x = Number{false, minMantissa * 10, 32768, Number::normalized{}};
41 }
42 catch (std::overflow_error const&)
43 {
44 caught = true;
45 }
46 BEAST_EXPECT(caught);
47
48 auto test = [this](auto const& x, auto const& y, int line) {
49 auto const result = x == y;
51 ss << x << " == " << y << " -> " << (result ? "true" : "false");
52 expect(result, ss.str(), __FILE__, line);
53 };
54
55 test(
56 Number{false, minMantissa * 10, 32767, Number::normalized{}},
57 Number{false, minMantissa, 32768, Number::normalized{}},
58 __LINE__);
59 test(Number{false, minMantissa, -32769, Number::normalized{}}, Number{}, __LINE__);
60 test(
61 Number{false, minMantissa, 32000, Number::normalized{}} * 1'000 +
62 Number{false, 1'500, 32000, Number::normalized{}},
63 Number{false, minMantissa + 2, 32003, Number::normalized{}},
64 __LINE__);
65 // 9,223,372,036,854,775,808
66
67 test(
69 scale == MantissaRange::small ? Number{-9'223'372'036'854'776, 3}
70 : Number{true, 9'223'372'036'854'775'808ULL, 0, Number::normalized{}},
71 __LINE__);
72 test(
74 scale == MantissaRange::small ? Number{-9'223'372'036'854'776, 3} : Number{-9'223'372'036'854'775'807},
75 __LINE__);
76 test(
78 Number{
79 scale == MantissaRange::small ? 9'223'372'036'854'776 : std::numeric_limits<std::int64_t>::max(),
80 18 - Number::mantissaLog()},
81 __LINE__);
82 caught = false;
83 try
84 {
85 [[maybe_unused]]
86 Number q = Number{false, minMantissa, 32767, Number::normalized{}} * 100;
87 }
88 catch (std::overflow_error const&)
89 {
90 caught = true;
91 }
92 BEAST_EXPECT(caught);
93 }
94
95 void
97 {
98 auto const scale = Number::getMantissaScale();
99 testcase << "test_add " << to_string(scale);
100
102 auto const cSmall = std::to_array<Case>(
103 {{Number{1'000'000'000'000'000, -15},
104 Number{6'555'555'555'555'555, -29},
105 Number{1'000'000'000'000'066, -15}},
106 {Number{-1'000'000'000'000'000, -15},
107 Number{-6'555'555'555'555'555, -29},
108 Number{-1'000'000'000'000'066, -15}},
109 {Number{-1'000'000'000'000'000, -15},
110 Number{6'555'555'555'555'555, -29},
111 Number{-9'999'999'999'999'344, -16}},
112 {Number{-6'555'555'555'555'555, -29},
113 Number{1'000'000'000'000'000, -15},
114 Number{9'999'999'999'999'344, -16}},
115 {Number{}, Number{5}, Number{5}},
116 {Number{5}, Number{}, Number{5}},
117 {Number{5'555'555'555'555'555, -32768}, Number{-5'555'555'555'555'554, -32768}, Number{0}},
118 {Number{-9'999'999'999'999'999, -31},
119 Number{1'000'000'000'000'000, -15},
120 Number{9'999'999'999'999'990, -16}}});
121 auto const cLarge = std::to_array<Case>(
122 // Note that items with extremely large mantissas need to be
123 // calculated, because otherwise they overflow uint64. Items from C
124 // with larger mantissa
125 {
126 {Number{1'000'000'000'000'000, -15},
127 Number{6'555'555'555'555'555, -29},
128 Number{1'000'000'000'000'065'556, -18}},
129 {Number{-1'000'000'000'000'000, -15},
130 Number{-6'555'555'555'555'555, -29},
131 Number{-1'000'000'000'000'065'556, -18}},
132 {Number{-1'000'000'000'000'000, -15},
133 Number{6'555'555'555'555'555, -29},
134 Number{true, 9'999'999'999'999'344'444ULL, -19, Number::normalized{}}},
135 {Number{-6'555'555'555'555'555, -29},
136 Number{1'000'000'000'000'000, -15},
137 Number{false, 9'999'999'999'999'344'444ULL, -19, Number::normalized{}}},
138 {Number{}, Number{5}, Number{5}},
139 {Number{5}, Number{}, Number{5}},
140 {Number{5'555'555'555'555'555'000, -32768}, Number{-5'555'555'555'555'554'000, -32768}, Number{0}},
141 {Number{-9'999'999'999'999'999, -31},
142 Number{1'000'000'000'000'000, -15},
143 Number{9'999'999'999'999'990, -16}},
144 // Items from cSmall expanded for the larger mantissa
145 {Number{1'000'000'000'000'000'000, -18},
146 Number{6'555'555'555'555'555'555, -35},
147 Number{1'000'000'000'000'000'066, -18}},
148 {Number{-1'000'000'000'000'000'000, -18},
149 Number{-6'555'555'555'555'555'555, -35},
150 Number{-1'000'000'000'000'000'066, -18}},
151 {Number{-1'000'000'000'000'000'000, -18},
152 Number{6'555'555'555'555'555'555, -35},
153 Number{true, 9'999'999'999'999'999'344ULL, -19, Number::normalized{}}},
154 {Number{-6'555'555'555'555'555'555, -35},
155 Number{1'000'000'000'000'000'000, -18},
156 Number{false, 9'999'999'999'999'999'344ULL, -19, Number::normalized{}}},
157 {Number{}, Number{5}, Number{5}},
158 {Number{5'555'555'555'555'555'555, -32768}, Number{-5'555'555'555'555'555'554, -32768}, Number{0}},
159 {Number{true, 9'999'999'999'999'999'999ULL, -37, Number::normalized{}},
160 Number{1'000'000'000'000'000'000, -18},
161 Number{false, 9'999'999'999'999'999'990ULL, -19, Number::normalized{}}},
162 {Number{Number::maxRep}, Number{6, -1}, Number{Number::maxRep / 10, 1}},
164 // Test extremes
165 {
166 // Each Number operand rounds up, so the actual mantissa is
167 // minMantissa
168 Number{false, 9'999'999'999'999'999'999ULL, 0, Number::normalized{}},
169 Number{false, 9'999'999'999'999'999'999ULL, 0, Number::normalized{}},
170 Number{2, 19},
171 },
172 {
173 // Does not round. Mantissas are going to be > maxRep, so if
174 // added together as uint64_t's, the result will overflow.
175 // With addition using uint128_t, there's no problem. After
176 // normalizing, the resulting mantissa ends up less than
177 // maxRep.
178 Number{false, 9'999'999'999'999'999'990ULL, 0, Number::normalized{}},
179 Number{false, 9'999'999'999'999'999'990ULL, 0, Number::normalized{}},
180 Number{false, 1'999'999'999'999'999'998ULL, 1, Number::normalized{}},
181 },
182 });
183 auto test = [this](auto const& c) {
184 for (auto const& [x, y, z] : c)
185 {
186 auto const result = x + y;
188 ss << x << " + " << y << " = " << result << ". Expected: " << z;
189 BEAST_EXPECTS(result == z, ss.str());
190 }
191 };
192 if (scale == MantissaRange::small)
193 test(cSmall);
194 else
195 test(cLarge);
196 {
197 bool caught = false;
198 try
199 {
200 Number{false, Number::maxMantissa(), 32768, Number::normalized{}} +
201 Number{false, Number::minMantissa(), 32767, Number::normalized{}} * 5;
202 }
203 catch (std::overflow_error const&)
204 {
205 caught = true;
206 }
207 BEAST_EXPECT(caught);
208 }
209 }
210
211 void
213 {
214 auto const scale = Number::getMantissaScale();
215 testcase << "test_sub " << to_string(scale);
216
218 auto const cSmall = std::to_array<Case>(
219 {{Number{1'000'000'000'000'000, -15},
220 Number{6'555'555'555'555'555, -29},
221 Number{9'999'999'999'999'344, -16}},
222 {Number{6'555'555'555'555'555, -29},
223 Number{1'000'000'000'000'000, -15},
224 Number{-9'999'999'999'999'344, -16}},
225 {Number{1'000'000'000'000'000, -15}, Number{1'000'000'000'000'000, -15}, Number{0}},
226 {Number{1'000'000'000'000'000, -15},
227 Number{1'000'000'000'000'001, -15},
228 Number{-1'000'000'000'000'000, -30}},
229 {Number{1'000'000'000'000'001, -15},
230 Number{1'000'000'000'000'000, -15},
231 Number{1'000'000'000'000'000, -30}}});
232 auto const cLarge = std::to_array<Case>(
233 // Note that items with extremely large mantissas need to be
234 // calculated, because otherwise they overflow uint64. Items from C
235 // with larger mantissa
236 {
237 {Number{1'000'000'000'000'000, -15},
238 Number{6'555'555'555'555'555, -29},
239 Number{false, 9'999'999'999'999'344'444ULL, -19, Number::normalized{}}},
240 {Number{6'555'555'555'555'555, -29},
241 Number{1'000'000'000'000'000, -15},
242 Number{true, 9'999'999'999'999'344'444ULL, -19, Number::normalized{}}},
243 {Number{1'000'000'000'000'000, -15}, Number{1'000'000'000'000'000, -15}, Number{0}},
244 {Number{1'000'000'000'000'000, -15},
245 Number{1'000'000'000'000'001, -15},
246 Number{-1'000'000'000'000'000, -30}},
247 {Number{1'000'000'000'000'001, -15},
248 Number{1'000'000'000'000'000, -15},
249 Number{1'000'000'000'000'000, -30}},
250 // Items from cSmall expanded for the larger mantissa
251 {Number{1'000'000'000'000'000'000, -18},
252 Number{6'555'555'555'555'555'555, -32},
253 Number{false, 9'999'999'999'999'344'444ULL, -19, Number::normalized{}}},
254 {Number{6'555'555'555'555'555'555, -32},
255 Number{1'000'000'000'000'000'000, -18},
256 Number{true, 9'999'999'999'999'344'444ULL, -19, Number::normalized{}}},
257 {Number{1'000'000'000'000'000'000, -18}, Number{1'000'000'000'000'000'000, -18}, Number{0}},
258 {Number{1'000'000'000'000'000'000, -18},
259 Number{1'000'000'000'000'000'001, -18},
260 Number{-1'000'000'000'000'000'000, -36}},
261 {Number{1'000'000'000'000'000'001, -18},
262 Number{1'000'000'000'000'000'000, -18},
263 Number{1'000'000'000'000'000'000, -36}},
265 {Number{false, Number::maxRep + 1, 0, Number::normalized{}},
266 Number{1, 0},
267 Number{Number::maxRep / 10 + 1, 1}},
269 {power(2, 63), Number{3, 0}, Number{Number::maxRep}},
270 });
271 auto test = [this](auto const& c) {
272 for (auto const& [x, y, z] : c)
273 {
274 auto const result = x - y;
276 ss << x << " - " << y << " = " << result << ". Expected: " << z;
277 BEAST_EXPECTS(result == z, ss.str());
278 }
279 };
280 if (scale == MantissaRange::small)
281 test(cSmall);
282 else
283 test(cLarge);
284 }
285
286 void
288 {
289 auto const scale = Number::getMantissaScale();
290 testcase << "test_mul " << to_string(scale);
291
293 auto test = [this](auto const& c) {
294 for (auto const& [x, y, z] : c)
295 {
296 auto const result = x * y;
298 ss << x << " * " << y << " = " << result << ". Expected: " << z;
299 BEAST_EXPECTS(result == z, ss.str());
300 }
301 };
302 auto tests = [&](auto const& cSmall, auto const& cLarge) {
303 if (scale == MantissaRange::small)
304 test(cSmall);
305 else
306 test(cLarge);
307 };
308 auto const maxMantissa = Number::maxMantissa();
309
311 {
312 auto const cSmall = std::to_array<Case>({
313 {Number{7}, Number{8}, Number{56}},
314 {Number{1414213562373095, -15}, Number{1414213562373095, -15}, Number{2000000000000000, -15}},
315 {Number{-1414213562373095, -15}, Number{1414213562373095, -15}, Number{-2000000000000000, -15}},
316 {Number{-1414213562373095, -15}, Number{-1414213562373095, -15}, Number{2000000000000000, -15}},
317 {Number{3214285714285706, -15}, Number{3111111111111119, -15}, Number{1000000000000000, -14}},
318 {Number{1000000000000000, -32768}, Number{1000000000000000, -32768}, Number{0}},
319 // Maximum mantissa range
320 {Number{9'999'999'999'999'999, 0}, Number{9'999'999'999'999'999, 0}, Number{9'999'999'999'999'998, 16}},
321 });
322 auto const cLarge = std::to_array<Case>({
323 // Note that items with extremely large mantissas need to be
324 // calculated, because otherwise they overflow uint64. Items
325 // from C with larger mantissa
326 {Number{7}, Number{8}, Number{56}},
327 {Number{1414213562373095, -15}, Number{1414213562373095, -15}, Number{1999999999999999862, -18}},
328 {Number{-1414213562373095, -15}, Number{1414213562373095, -15}, Number{-1999999999999999862, -18}},
329 {Number{-1414213562373095, -15}, Number{-1414213562373095, -15}, Number{1999999999999999862, -18}},
330 {Number{3214285714285706, -15},
331 Number{3111111111111119, -15},
332 Number{false, 9'999'999'999'999'999'579ULL, -18, Number::normalized{}}},
333 {Number{1000000000000000000, -32768}, Number{1000000000000000000, -32768}, Number{0}},
334 // Items from cSmall expanded for the larger mantissa,
335 // except duplicates. Sadly, it looks like sqrt(2)^2 != 2
336 // with higher precision
337 {Number{1414213562373095049, -18}, Number{1414213562373095049, -18}, Number{2000000000000000001, -18}},
338 {Number{-1414213562373095048, -18},
339 Number{1414213562373095048, -18},
340 Number{-1999999999999999998, -18}},
341 {Number{-1414213562373095048, -18},
342 Number{-1414213562373095049, -18},
343 Number{1999999999999999999, -18}},
344 {Number{3214285714285714278, -18}, Number{3111111111111111119, -18}, Number{10, 0}},
345 // Maximum mantissa range - rounds up to 1e19
348 Number{1, 38}},
349 // Maximum int64 range
350 {Number{Number::maxRep, 0}, Number{Number::maxRep, 0}, Number{85'070'591'730'234'615'85, 19}},
351 });
352 tests(cSmall, cLarge);
353 }
355 testcase << "test_mul " << to_string(Number::getMantissaScale()) << " towards_zero";
356 {
357 auto const cSmall = std::to_array<Case>(
358 {{Number{7}, Number{8}, Number{56}},
359 {Number{1414213562373095, -15}, Number{1414213562373095, -15}, Number{1999999999999999, -15}},
360 {Number{-1414213562373095, -15}, Number{1414213562373095, -15}, Number{-1999999999999999, -15}},
361 {Number{-1414213562373095, -15}, Number{-1414213562373095, -15}, Number{1999999999999999, -15}},
362 {Number{3214285714285706, -15}, Number{3111111111111119, -15}, Number{9999999999999999, -15}},
363 {Number{1000000000000000, -32768}, Number{1000000000000000, -32768}, Number{0}}});
364 auto const cLarge = std::to_array<Case>(
365 // Note that items with extremely large mantissas need to be
366 // calculated, because otherwise they overflow uint64. Items
367 // from C with larger mantissa
368 {
369 {Number{7}, Number{8}, Number{56}},
370 {Number{1414213562373095, -15}, Number{1414213562373095, -15}, Number{1999999999999999861, -18}},
371 {Number{-1414213562373095, -15}, Number{1414213562373095, -15}, Number{-1999999999999999861, -18}},
372 {Number{-1414213562373095, -15}, Number{-1414213562373095, -15}, Number{1999999999999999861, -18}},
373 {Number{3214285714285706, -15},
374 Number{3111111111111119, -15},
375 Number{false, 9999999999999999579ULL, -18, Number::normalized{}}},
376 {Number{1000000000000000000, -32768}, Number{1000000000000000000, -32768}, Number{0}},
377 // Items from cSmall expanded for the larger mantissa,
378 // except duplicates. Sadly, it looks like sqrt(2)^2 != 2
379 // with higher precision
380 {Number{1414213562373095049, -18}, Number{1414213562373095049, -18}, Number{2, 0}},
381 {Number{-1414213562373095048, -18},
382 Number{1414213562373095048, -18},
383 Number{-1999999999999999997, -18}},
384 {Number{-1414213562373095048, -18},
385 Number{-1414213562373095049, -18},
386 Number{1999999999999999999, -18}},
387 {Number{3214285714285714278, -18}, Number{3111111111111111119, -18}, Number{10, 0}},
388 // Maximum mantissa range - rounds down to maxMantissa/10e1
389 // 99'999'999'999'999'999'800'000'000'000'000'000'100
392 Number{false, maxMantissa / 10 - 1, 20, Number::normalized{}}},
393 // Maximum int64 range
394 // 85'070'591'730'234'615'847'396'907'784'232'501'249
395 {Number{Number::maxRep, 0}, Number{Number::maxRep, 0}, Number{85'070'591'730'234'615'84, 19}},
396 });
397 tests(cSmall, cLarge);
398 }
400 testcase << "test_mul " << to_string(Number::getMantissaScale()) << " downward";
401 {
402 auto const cSmall = std::to_array<Case>(
403 {{Number{7}, Number{8}, Number{56}},
404 {Number{1414213562373095, -15}, Number{1414213562373095, -15}, Number{1999999999999999, -15}},
405 {Number{-1414213562373095, -15}, Number{1414213562373095, -15}, Number{-2000000000000000, -15}},
406 {Number{-1414213562373095, -15}, Number{-1414213562373095, -15}, Number{1999999999999999, -15}},
407 {Number{3214285714285706, -15}, Number{3111111111111119, -15}, Number{9999999999999999, -15}},
408 {Number{1000000000000000, -32768}, Number{1000000000000000, -32768}, Number{0}}});
409 auto const cLarge = std::to_array<Case>(
410 // Note that items with extremely large mantissas need to be
411 // calculated, because otherwise they overflow uint64. Items
412 // from C with larger mantissa
413 {
414 {Number{7}, Number{8}, Number{56}},
415 {Number{1414213562373095, -15}, Number{1414213562373095, -15}, Number{1999999999999999861, -18}},
416 {Number{-1414213562373095, -15}, Number{1414213562373095, -15}, Number{-1999999999999999862, -18}},
417 {Number{-1414213562373095, -15}, Number{-1414213562373095, -15}, Number{1999999999999999861, -18}},
418 {Number{3214285714285706, -15},
419 Number{3111111111111119, -15},
420 Number{false, 9'999'999'999'999'999'579ULL, -18, Number::normalized{}}},
421 {Number{1000000000000000000, -32768}, Number{1000000000000000000, -32768}, Number{0}},
422 // Items from cSmall expanded for the larger mantissa,
423 // except duplicates. Sadly, it looks like sqrt(2)^2 != 2
424 // with higher precision
425 {Number{1414213562373095049, -18}, Number{1414213562373095049, -18}, Number{2, 0}},
426 {Number{-1414213562373095048, -18},
427 Number{1414213562373095048, -18},
428 Number{-1999999999999999998, -18}},
429 {Number{-1414213562373095048, -18},
430 Number{-1414213562373095049, -18},
431 Number{1999999999999999999, -18}},
432 {Number{3214285714285714278, -18}, Number{3111111111111111119, -18}, Number{10, 0}},
433 // Maximum mantissa range - rounds down to maxMantissa/10e1
434 // 99'999'999'999'999'999'800'000'000'000'000'000'100
437 Number{false, maxMantissa / 10 - 1, 20, Number::normalized{}}},
438 // Maximum int64 range
439 // 85'070'591'730'234'615'847'396'907'784'232'501'249
440 {Number{Number::maxRep, 0}, Number{Number::maxRep, 0}, Number{85'070'591'730'234'615'84, 19}},
441 });
442 tests(cSmall, cLarge);
443 }
445 testcase << "test_mul " << to_string(Number::getMantissaScale()) << " upward";
446 {
447 auto const cSmall = std::to_array<Case>(
448 {{Number{7}, Number{8}, Number{56}},
449 {Number{1414213562373095, -15}, Number{1414213562373095, -15}, Number{2000000000000000, -15}},
450 {Number{-1414213562373095, -15}, Number{1414213562373095, -15}, Number{-1999999999999999, -15}},
451 {Number{-1414213562373095, -15}, Number{-1414213562373095, -15}, Number{2000000000000000, -15}},
452 {Number{3214285714285706, -15}, Number{3111111111111119, -15}, Number{1000000000000000, -14}},
453 {Number{1000000000000000, -32768}, Number{1000000000000000, -32768}, Number{0}}});
454 auto const cLarge = std::to_array<Case>(
455 // Note that items with extremely large mantissas need to be
456 // calculated, because otherwise they overflow uint64. Items
457 // from C with larger mantissa
458 {
459 {Number{7}, Number{8}, Number{56}},
460 {Number{1414213562373095, -15}, Number{1414213562373095, -15}, Number{1999999999999999862, -18}},
461 {Number{-1414213562373095, -15}, Number{1414213562373095, -15}, Number{-1999999999999999861, -18}},
462 {Number{-1414213562373095, -15}, Number{-1414213562373095, -15}, Number{1999999999999999862, -18}},
463 {Number{3214285714285706, -15}, Number{3111111111111119, -15}, Number{999999999999999958, -17}},
464 {Number{1000000000000000000, -32768}, Number{1000000000000000000, -32768}, Number{0}},
465 // Items from cSmall expanded for the larger mantissa,
466 // except duplicates. Sadly, it looks like sqrt(2)^2 != 2
467 // with higher precision
468 {Number{1414213562373095049, -18},
469 Number{1414213562373095049, -18},
470 Number{2000000000000000001, -18}},
471 {Number{-1414213562373095048, -18},
472 Number{1414213562373095048, -18},
473 Number{-1999999999999999997, -18}},
474 {Number{-1414213562373095048, -18}, Number{-1414213562373095049, -18}, Number{2, 0}},
475 {Number{3214285714285714278, -18},
476 Number{3111111111111111119, -18},
477 Number{1000000000000000001, -17}},
478 // Maximum mantissa range - rounds up to minMantissa*10
479 // 1e19*1e19=1e38
482 Number{1, 38}},
483 // Maximum int64 range
484 // 85'070'591'730'234'615'847'396'907'784'232'501'249
485 {Number{Number::maxRep, 0}, Number{Number::maxRep, 0}, Number{85'070'591'730'234'615'85, 19}},
486 });
487 tests(cSmall, cLarge);
488 }
489 testcase << "test_mul " << to_string(Number::getMantissaScale()) << " overflow";
490 {
491 bool caught = false;
492 try
493 {
494 Number{false, maxMantissa, 32768, Number::normalized{}} *
495 Number{false, Number::minMantissa() * 5, 32767, Number::normalized{}};
496 }
497 catch (std::overflow_error const&)
498 {
499 caught = true;
500 }
501 BEAST_EXPECT(caught);
502 }
503 }
504
505 void
507 {
508 auto const scale = Number::getMantissaScale();
509 testcase << "test_div " << to_string(scale);
510
512 auto test = [this](auto const& c) {
513 for (auto const& [x, y, z] : c)
514 {
515 auto const result = x / y;
517 ss << x << " / " << y << " = " << result << ". Expected: " << z;
518 BEAST_EXPECTS(result == z, ss.str());
519 }
520 };
521 auto const maxMantissa = Number::maxMantissa();
522 auto tests = [&](auto const& cSmall, auto const& cLarge) {
523 if (scale == MantissaRange::small)
524 test(cSmall);
525 else
526 test(cLarge);
527 };
529 {
530 auto const cSmall = std::to_array<Case>(
531 {{Number{1}, Number{2}, Number{5, -1}},
532 {Number{1}, Number{10}, Number{1, -1}},
533 {Number{1}, Number{-10}, Number{-1, -1}},
534 {Number{0}, Number{100}, Number{0}},
535 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
536 {Number{9'999'999'999'999'999}, Number{1'000'000'000'000'000}, Number{9'999'999'999'999'999, -15}},
537 {Number{2}, Number{3}, Number{6'666'666'666'666'667, -16}},
538 {Number{-2}, Number{3}, Number{-6'666'666'666'666'667, -16}},
539 {Number{1}, Number{7}, Number{1'428'571'428'571'428, -16}}});
540 auto const cLarge = std::to_array<Case>(
541 // Note that items with extremely large mantissas need to be
542 // calculated, because otherwise they overflow uint64. Items
543 // from C with larger mantissa
544 {{Number{1}, Number{2}, Number{5, -1}},
545 {Number{1}, Number{10}, Number{1, -1}},
546 {Number{1}, Number{-10}, Number{-1, -1}},
547 {Number{0}, Number{100}, Number{0}},
548 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
549 {Number{9'999'999'999'999'999}, Number{1'000'000'000'000'000}, Number{9'999'999'999'999'999, -15}},
550 {Number{2}, Number{3}, Number{6'666'666'666'666'666'667, -19}},
551 {Number{-2}, Number{3}, Number{-6'666'666'666'666'666'667, -19}},
552 {Number{1}, Number{7}, Number{1'428'571'428'571'428'571, -19}},
553 // Items from cSmall expanded for the larger mantissa, except
554 // duplicates.
555 {Number{1414213562373095049, -13}, Number{1414213562373095049, -13}, Number{1}},
557 Number{1'000'000'000'000'000'000},
558 Number{false, maxMantissa, -18, Number::normalized{}}}});
559 tests(cSmall, cLarge);
560 }
561 testcase << "test_div " << to_string(Number::getMantissaScale()) << " towards_zero";
563 {
564 auto const cSmall = std::to_array<Case>(
565 {{Number{1}, Number{2}, Number{5, -1}},
566 {Number{1}, Number{10}, Number{1, -1}},
567 {Number{1}, Number{-10}, Number{-1, -1}},
568 {Number{0}, Number{100}, Number{0}},
569 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
570 {Number{9'999'999'999'999'999}, Number{1'000'000'000'000'000}, Number{9'999'999'999'999'999, -15}},
571 {Number{2}, Number{3}, Number{6'666'666'666'666'666, -16}},
572 {Number{-2}, Number{3}, Number{-6'666'666'666'666'666, -16}},
573 {Number{1}, Number{7}, Number{1'428'571'428'571'428, -16}}});
574 auto const cLarge = std::to_array<Case>(
575 // Note that items with extremely large mantissas need to be
576 // calculated, because otherwise they overflow uint64. Items
577 // from C with larger mantissa
578 {{Number{1}, Number{2}, Number{5, -1}},
579 {Number{1}, Number{10}, Number{1, -1}},
580 {Number{1}, Number{-10}, Number{-1, -1}},
581 {Number{0}, Number{100}, Number{0}},
582 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
583 {Number{9'999'999'999'999'999}, Number{1'000'000'000'000'000}, Number{9'999'999'999'999'999, -15}},
584 {Number{2}, Number{3}, Number{6'666'666'666'666'666'666, -19}},
585 {Number{-2}, Number{3}, Number{-6'666'666'666'666'666'666, -19}},
586 {Number{1}, Number{7}, Number{1'428'571'428'571'428'571, -19}},
587 // Items from cSmall expanded for the larger mantissa, except
588 // duplicates.
589 {Number{1414213562373095049, -13}, Number{1414213562373095049, -13}, Number{1}},
591 Number{1'000'000'000'000'000'000},
592 Number{false, maxMantissa, -18, Number::normalized{}}}});
593 tests(cSmall, cLarge);
594 }
595 testcase << "test_div " << to_string(Number::getMantissaScale()) << " downward";
597 {
598 auto const cSmall = std::to_array<Case>(
599 {{Number{1}, Number{2}, Number{5, -1}},
600 {Number{1}, Number{10}, Number{1, -1}},
601 {Number{1}, Number{-10}, Number{-1, -1}},
602 {Number{0}, Number{100}, Number{0}},
603 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
604 {Number{9'999'999'999'999'999}, Number{1'000'000'000'000'000}, Number{9'999'999'999'999'999, -15}},
605 {Number{2}, Number{3}, Number{6'666'666'666'666'666, -16}},
606 {Number{-2}, Number{3}, Number{-6'666'666'666'666'667, -16}},
607 {Number{1}, Number{7}, Number{1'428'571'428'571'428, -16}}});
608 auto const cLarge = std::to_array<Case>(
609 // Note that items with extremely large mantissas need to be
610 // calculated, because otherwise they overflow uint64. Items
611 // from C with larger mantissa
612 {{Number{1}, Number{2}, Number{5, -1}},
613 {Number{1}, Number{10}, Number{1, -1}},
614 {Number{1}, Number{-10}, Number{-1, -1}},
615 {Number{0}, Number{100}, Number{0}},
616 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
617 {Number{9'999'999'999'999'999}, Number{1'000'000'000'000'000}, Number{9'999'999'999'999'999, -15}},
618 {Number{2}, Number{3}, Number{6'666'666'666'666'666'666, -19}},
619 {Number{-2}, Number{3}, Number{-6'666'666'666'666'666'667, -19}},
620 {Number{1}, Number{7}, Number{1'428'571'428'571'428'571, -19}},
621 // Items from cSmall expanded for the larger mantissa, except
622 // duplicates.
623 {Number{1414213562373095049, -13}, Number{1414213562373095049, -13}, Number{1}},
625 Number{1'000'000'000'000'000'000},
626 Number{false, maxMantissa, -18, Number::normalized{}}}});
627 tests(cSmall, cLarge);
628 }
629 testcase << "test_div " << to_string(Number::getMantissaScale()) << " upward";
631 {
632 auto const cSmall = std::to_array<Case>(
633 {{Number{1}, Number{2}, Number{5, -1}},
634 {Number{1}, Number{10}, Number{1, -1}},
635 {Number{1}, Number{-10}, Number{-1, -1}},
636 {Number{0}, Number{100}, Number{0}},
637 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
638 {Number{9'999'999'999'999'999}, Number{1'000'000'000'000'000}, Number{9'999'999'999'999'999, -15}},
639 {Number{2}, Number{3}, Number{6'666'666'666'666'667, -16}},
640 {Number{-2}, Number{3}, Number{-6'666'666'666'666'666, -16}},
641 {Number{1}, Number{7}, Number{1'428'571'428'571'429, -16}}});
642 auto const cLarge = std::to_array<Case>(
643 // Note that items with extremely large mantissas need to be
644 // calculated, because otherwise they overflow uint64. Items
645 // from C with larger mantissa
646 {{Number{1}, Number{2}, Number{5, -1}},
647 {Number{1}, Number{10}, Number{1, -1}},
648 {Number{1}, Number{-10}, Number{-1, -1}},
649 {Number{0}, Number{100}, Number{0}},
650 {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}},
651 {Number{9'999'999'999'999'999}, Number{1'000'000'000'000'000}, Number{9'999'999'999'999'999, -15}},
652 {Number{2}, Number{3}, Number{6'666'666'666'666'666'667, -19}},
653 {Number{-2}, Number{3}, Number{-6'666'666'666'666'666'666, -19}},
654 {Number{1}, Number{7}, Number{1'428'571'428'571'428'572, -19}},
655 // Items from cSmall expanded for the larger mantissa, except
656 // duplicates.
657 {Number{1414213562373095049, -13}, Number{1414213562373095049, -13}, Number{1}},
659 Number{1'000'000'000'000'000'000},
660 Number{false, maxMantissa, -18, Number::normalized{}}}});
661 tests(cSmall, cLarge);
662 }
663 testcase << "test_div " << to_string(Number::getMantissaScale()) << " overflow";
664 bool caught = false;
665 try
666 {
667 Number{1000000000000000, -15} / Number{0};
668 }
669 catch (std::overflow_error const&)
670 {
671 caught = true;
672 }
673 BEAST_EXPECT(caught);
674 }
675
676 void
678 {
679 auto const scale = Number::getMantissaScale();
680 testcase << "test_root " << to_string(scale);
681
683 auto test = [this](auto const& c) {
684 for (auto const& [x, y, z] : c)
685 {
686 auto const result = root(x, y);
688 ss << "root(" << x << ", " << y << ") = " << result << ". Expected: " << z;
689 BEAST_EXPECTS(result == z, ss.str());
690 }
691 };
692 /*
693 auto tests = [&](auto const& cSmall, auto const& cLarge) {
694 test(cSmall);
695 if (scale != MantissaRange::small)
696 test(cLarge);
697 };
698 */
699
700 auto const cSmall = std::to_array<Case>(
701 {{Number{2}, 2, Number{1414213562373095049, -18}},
702 {Number{2'000'000}, 2, Number{1414213562373095049, -15}},
703 {Number{2, -30}, 2, Number{1414213562373095049, -33}},
704 {Number{-27}, 3, Number{-3}},
705 {Number{1}, 5, Number{1}},
706 {Number{-1}, 0, Number{1}},
707 {Number{5, -1}, 0, Number{0}},
708 {Number{0}, 5, Number{0}},
709 {Number{5625, -4}, 2, Number{75, -2}}});
710 auto const cLarge = std::to_array<Case>({
711 {Number{false, Number::maxMantissa() - 9, -1, Number::normalized{}},
712 2,
713 Number{false, 999'999'999'999'999'999, -9, Number::normalized{}}},
714 {Number{false, Number::maxMantissa() - 9, 0, Number::normalized{}},
715 2,
716 Number{false, 3'162'277'660'168'379'330, -9, Number::normalized{}}},
717 {Number{Number::maxRep}, 2, Number{false, 3'037'000'499'976049692, -9, Number::normalized{}}},
718 {Number{Number::maxRep}, 4, Number{false, 55'108'98747006743627, -14, Number::normalized{}}},
719 });
720 test(cSmall);
722 {
724 test(cLarge);
725 }
726 bool caught = false;
727 try
728 {
729 (void)root(Number{-2}, 0);
730 }
731 catch (std::overflow_error const&)
732 {
733 caught = true;
734 }
735 BEAST_EXPECT(caught);
736 caught = false;
737 try
738 {
739 (void)root(Number{-2}, 4);
740 }
741 catch (std::overflow_error const&)
742 {
743 caught = true;
744 }
745 BEAST_EXPECT(caught);
746 }
747
748 void
750 {
751 auto const scale = Number::getMantissaScale();
752 testcase << "test_root2 " << to_string(scale);
753
754 auto test = [this](auto const& c) {
755 for (auto const& x : c)
756 {
757 auto const expected = root(x, 2);
758 auto const result = root2(x);
760 ss << "root2(" << x << ") = " << result << ". Expected: " << expected;
761 BEAST_EXPECTS(result == expected, ss.str());
762 }
763 };
764
765 auto const cSmall = std::to_array<Number>({
766 Number{2},
767 Number{2'000'000},
768 Number{2, -30},
769 Number{27},
770 Number{1},
771 Number{5, -1},
772 Number{0},
773 Number{5625, -4},
775 });
776 test(cSmall);
777 bool caught = false;
778 try
779 {
780 (void)root2(Number{-2});
781 }
782 catch (std::overflow_error const&)
783 {
784 caught = true;
785 }
786 BEAST_EXPECT(caught);
787 }
788
789 void
791 {
792 testcase << "test_power1 " << to_string(Number::getMantissaScale());
794 Case c[]{
795 {Number{64}, 0, Number{1}},
796 {Number{64}, 1, Number{64}},
797 {Number{64}, 2, Number{4096}},
798 {Number{-64}, 2, Number{4096}},
799 {Number{64}, 3, Number{262144}},
800 {Number{-64}, 3, Number{-262144}},
801 {Number{64}, 11, Number{false, 7378697629483820646ULL, 1, Number::normalized{}}},
802 {Number{-64}, 11, Number{true, 7378697629483820646ULL, 1, Number::normalized{}}}};
803 for (auto const& [x, y, z] : c)
804 BEAST_EXPECT((power(x, y) == z));
805 }
806
807 void
809 {
810 testcase << "test_power2 " << to_string(Number::getMantissaScale());
812 Case c[]{
813 {Number{1}, 3, 7, Number{1}},
814 {Number{-1}, 1, 0, Number{1}},
815 {Number{-1, -1}, 1, 0, Number{0}},
816 {Number{16}, 0, 5, Number{1}},
817 {Number{34}, 3, 3, Number{34}},
818 {Number{4}, 3, 2, Number{8}}};
819 for (auto const& [x, n, d, z] : c)
820 BEAST_EXPECT((power(x, n, d) == z));
821 bool caught = false;
822 try
823 {
824 (void)power(Number{7}, 0, 0);
825 }
826 catch (std::overflow_error const&)
827 {
828 caught = true;
829 }
830 BEAST_EXPECT(caught);
831 caught = false;
832 try
833 {
834 (void)power(Number{7}, 1, 0);
835 }
836 catch (std::overflow_error const&)
837 {
838 caught = true;
839 }
840 BEAST_EXPECT(caught);
841 caught = false;
842 try
843 {
844 (void)power(Number{-1, -1}, 3, 2);
845 }
846 catch (std::overflow_error const&)
847 {
848 caught = true;
849 }
850 BEAST_EXPECT(caught);
851 }
852
853 void
855 {
856 testcase << "testConversions " << to_string(Number::getMantissaScale());
857
858 IOUAmount x{5, 6};
859 Number y = x;
860 BEAST_EXPECT((y == Number{5, 6}));
861 IOUAmount z{y};
862 BEAST_EXPECT(x == z);
863 XRPAmount xrp{500};
864 STAmount st = xrp;
865 Number n = st;
866 BEAST_EXPECT(XRPAmount{n} == xrp);
867 IOUAmount x0{0, 0};
868 Number y0 = x0;
869 BEAST_EXPECT((y0 == Number{0}));
870 IOUAmount z0{y0};
871 BEAST_EXPECT(x0 == z0);
872 XRPAmount xrp0{0};
873 Number n0 = xrp0;
874 BEAST_EXPECT(n0 == Number{0});
875 XRPAmount xrp1{n0};
876 BEAST_EXPECT(xrp1 == xrp0);
877 }
878
879 void
881 {
882 testcase << "test_to_integer " << to_string(Number::getMantissaScale());
885 {
886 Case c[]{
887 {Number{0}, 0},
888 {Number{1}, 1},
889 {Number{2}, 2},
890 {Number{3}, 3},
891 {Number{-1}, -1},
892 {Number{-2}, -2},
893 {Number{-3}, -3},
894 {Number{10}, 10},
895 {Number{99}, 99},
896 {Number{1155}, 1155},
897 {Number{9'999'999'999'999'999, 0}, 9'999'999'999'999'999},
898 {Number{9'999'999'999'999'999, 1}, 99'999'999'999'999'990},
899 {Number{9'999'999'999'999'999, 2}, 999'999'999'999'999'900},
900 {Number{-9'999'999'999'999'999, 2}, -999'999'999'999'999'900},
901 {Number{15, -1}, 2},
902 {Number{14, -1}, 1},
903 {Number{16, -1}, 2},
904 {Number{25, -1}, 2},
905 {Number{6, -1}, 1},
906 {Number{5, -1}, 0},
907 {Number{4, -1}, 0},
908 {Number{-15, -1}, -2},
909 {Number{-14, -1}, -1},
910 {Number{-16, -1}, -2},
911 {Number{-25, -1}, -2},
912 {Number{-6, -1}, -1},
913 {Number{-5, -1}, 0},
914 {Number{-4, -1}, 0}};
915 for (auto const& [x, y] : c)
916 {
917 auto j = static_cast<std::int64_t>(x);
918 BEAST_EXPECT(j == y);
919 }
920 }
921 auto prev_mode = Number::setround(Number::towards_zero);
922 BEAST_EXPECT(prev_mode == Number::to_nearest);
923 {
924 Case c[]{
925 {Number{0}, 0},
926 {Number{1}, 1},
927 {Number{2}, 2},
928 {Number{3}, 3},
929 {Number{-1}, -1},
930 {Number{-2}, -2},
931 {Number{-3}, -3},
932 {Number{10}, 10},
933 {Number{99}, 99},
934 {Number{1155}, 1155},
935 {Number{9'999'999'999'999'999, 0}, 9'999'999'999'999'999},
936 {Number{9'999'999'999'999'999, 1}, 99'999'999'999'999'990},
937 {Number{9'999'999'999'999'999, 2}, 999'999'999'999'999'900},
938 {Number{-9'999'999'999'999'999, 2}, -999'999'999'999'999'900},
939 {Number{15, -1}, 1},
940 {Number{14, -1}, 1},
941 {Number{16, -1}, 1},
942 {Number{25, -1}, 2},
943 {Number{6, -1}, 0},
944 {Number{5, -1}, 0},
945 {Number{4, -1}, 0},
946 {Number{-15, -1}, -1},
947 {Number{-14, -1}, -1},
948 {Number{-16, -1}, -1},
949 {Number{-25, -1}, -2},
950 {Number{-6, -1}, 0},
951 {Number{-5, -1}, 0},
952 {Number{-4, -1}, 0}};
953 for (auto const& [x, y] : c)
954 {
955 auto j = static_cast<std::int64_t>(x);
956 BEAST_EXPECT(j == y);
957 }
958 }
960 BEAST_EXPECT(prev_mode == Number::towards_zero);
961 {
962 Case c[]{
963 {Number{0}, 0},
964 {Number{1}, 1},
965 {Number{2}, 2},
966 {Number{3}, 3},
967 {Number{-1}, -1},
968 {Number{-2}, -2},
969 {Number{-3}, -3},
970 {Number{10}, 10},
971 {Number{99}, 99},
972 {Number{1155}, 1155},
973 {Number{9'999'999'999'999'999, 0}, 9'999'999'999'999'999},
974 {Number{9'999'999'999'999'999, 1}, 99'999'999'999'999'990},
975 {Number{9'999'999'999'999'999, 2}, 999'999'999'999'999'900},
976 {Number{-9'999'999'999'999'999, 2}, -999'999'999'999'999'900},
977 {Number{15, -1}, 1},
978 {Number{14, -1}, 1},
979 {Number{16, -1}, 1},
980 {Number{25, -1}, 2},
981 {Number{6, -1}, 0},
982 {Number{5, -1}, 0},
983 {Number{4, -1}, 0},
984 {Number{-15, -1}, -2},
985 {Number{-14, -1}, -2},
986 {Number{-16, -1}, -2},
987 {Number{-25, -1}, -3},
988 {Number{-6, -1}, -1},
989 {Number{-5, -1}, -1},
990 {Number{-4, -1}, -1}};
991 for (auto const& [x, y] : c)
992 {
993 auto j = static_cast<std::int64_t>(x);
994 BEAST_EXPECT(j == y);
995 }
996 }
997 prev_mode = Number::setround(Number::upward);
998 BEAST_EXPECT(prev_mode == Number::downward);
999 {
1000 Case c[]{
1001 {Number{0}, 0},
1002 {Number{1}, 1},
1003 {Number{2}, 2},
1004 {Number{3}, 3},
1005 {Number{-1}, -1},
1006 {Number{-2}, -2},
1007 {Number{-3}, -3},
1008 {Number{10}, 10},
1009 {Number{99}, 99},
1010 {Number{1155}, 1155},
1011 {Number{9'999'999'999'999'999, 0}, 9'999'999'999'999'999},
1012 {Number{9'999'999'999'999'999, 1}, 99'999'999'999'999'990},
1013 {Number{9'999'999'999'999'999, 2}, 999'999'999'999'999'900},
1014 {Number{-9'999'999'999'999'999, 2}, -999'999'999'999'999'900},
1015 {Number{15, -1}, 2},
1016 {Number{14, -1}, 2},
1017 {Number{16, -1}, 2},
1018 {Number{25, -1}, 3},
1019 {Number{6, -1}, 1},
1020 {Number{5, -1}, 1},
1021 {Number{4, -1}, 1},
1022 {Number{-15, -1}, -1},
1023 {Number{-14, -1}, -1},
1024 {Number{-16, -1}, -1},
1025 {Number{-25, -1}, -2},
1026 {Number{-6, -1}, 0},
1027 {Number{-5, -1}, 0},
1028 {Number{-4, -1}, 0}};
1029 for (auto const& [x, y] : c)
1030 {
1031 auto j = static_cast<std::int64_t>(x);
1032 BEAST_EXPECT(j == y);
1033 }
1034 }
1035 bool caught = false;
1036 try
1037 {
1038 (void)static_cast<std::int64_t>(Number{9223372036854776, 3});
1039 }
1040 catch (std::overflow_error const&)
1041 {
1042 caught = true;
1043 }
1044 BEAST_EXPECT(caught);
1045 }
1046
1047 void
1049 {
1050 testcase << "test_squelch " << to_string(Number::getMantissaScale());
1051 Number limit{1, -6};
1052 BEAST_EXPECT((squelch(Number{2, -6}, limit) == Number{2, -6}));
1053 BEAST_EXPECT((squelch(Number{1, -6}, limit) == Number{1, -6}));
1054 BEAST_EXPECT((squelch(Number{9, -7}, limit) == Number{0}));
1055 BEAST_EXPECT((squelch(Number{-2, -6}, limit) == Number{-2, -6}));
1056 BEAST_EXPECT((squelch(Number{-1, -6}, limit) == Number{-1, -6}));
1057 BEAST_EXPECT((squelch(Number{-9, -7}, limit) == Number{0}));
1058 }
1059
1060 void
1062 {
1063 auto const scale = Number::getMantissaScale();
1064 testcase << "testToString " << to_string(scale);
1065
1066 auto test = [this](Number const& n, std::string const& expected) {
1067 auto const result = to_string(n);
1069 ss << "to_string(" << result << "). Expected: " << expected;
1070 BEAST_EXPECTS(result == expected, ss.str());
1071 };
1072
1073 test(Number(-2, 0), "-2");
1074 test(Number(0, 0), "0");
1075 test(Number(2, 0), "2");
1076 test(Number(25, -3), "0.025");
1077 test(Number(-25, -3), "-0.025");
1078 test(Number(25, 1), "250");
1079 test(Number(-25, 1), "-250");
1080 test(Number(2, 20), "2e20");
1081 test(Number(-2, -20), "-2e-20");
1082 // Test the edges
1083 // ((exponent < -(25)) || (exponent > -(5)))))
1084 // or ((exponent < -(28)) || (exponent > -(8)))))
1085 test(Number(2, -10), "0.0000000002");
1086 test(Number(2, -11), "2e-11");
1087
1088 test(Number(-2, 10), "-20000000000");
1089 test(Number(-2, 11), "-2e11");
1090
1091 switch (scale)
1092 {
1094
1095 test(Number::min(), "1e-32753");
1096 test(Number::max(), "9999999999999999e32768");
1097 test(Number::lowest(), "-9999999999999999e32768");
1098 {
1100
1101 auto const maxMantissa = Number::maxMantissa();
1102 BEAST_EXPECT(maxMantissa == 9'999'999'999'999'999);
1103 test(Number{false, maxMantissa * 1000 + 999, -3, Number::normalized()}, "9999999999999999");
1104 test(Number{true, maxMantissa * 1000 + 999, -3, Number::normalized()}, "-9999999999999999");
1105
1106 test(Number{std::numeric_limits<std::int64_t>::max(), -3}, "9223372036854775");
1107 test(-(Number{std::numeric_limits<std::int64_t>::max(), -3}), "-9223372036854775");
1108
1109 test(Number{std::numeric_limits<std::int64_t>::min(), 0}, "-9223372036854775e3");
1110 test(-(Number{std::numeric_limits<std::int64_t>::min(), 0}), "9223372036854775e3");
1111 }
1112 break;
1114 // Test the edges
1115 // ((exponent < -(28)) || (exponent > -(8)))))
1116 test(Number::min(), "1e-32750");
1117 test(Number::max(), "9223372036854775807e32768");
1118 test(Number::lowest(), "-9223372036854775807e32768");
1119 {
1121
1122 auto const maxMantissa = Number::maxMantissa();
1123 BEAST_EXPECT(maxMantissa == 9'999'999'999'999'999'999ULL);
1124 test(Number{false, maxMantissa, 0, Number::normalized{}}, "9999999999999999990");
1125 test(Number{true, maxMantissa, 0, Number::normalized{}}, "-9999999999999999990");
1126
1127 test(Number{std::numeric_limits<std::int64_t>::max(), 0}, "9223372036854775807");
1128 test(-(Number{std::numeric_limits<std::int64_t>::max(), 0}), "-9223372036854775807");
1129
1130 // Because the absolute value of min is larger than max, it
1131 // will be scaled down to fit under max. Since we're
1132 // rounding towards zero, the 8 at the end is dropped.
1133 test(Number{std::numeric_limits<std::int64_t>::min(), 0}, "-9223372036854775800");
1134 test(-(Number{std::numeric_limits<std::int64_t>::min(), 0}), "9223372036854775800");
1135 }
1136
1137 test(Number{std::numeric_limits<std::int64_t>::max(), 0} + 1, "9223372036854775810");
1138 test(-(Number{std::numeric_limits<std::int64_t>::max(), 0} + 1), "-9223372036854775810");
1139 break;
1140 default:
1141 BEAST_EXPECT(false);
1142 }
1143 }
1144
1145 void
1147 {
1148 testcase << "test_relationals " << to_string(Number::getMantissaScale());
1149 BEAST_EXPECT(!(Number{100} < Number{10}));
1150 BEAST_EXPECT(Number{100} > Number{10});
1151 BEAST_EXPECT(Number{100} >= Number{10});
1152 BEAST_EXPECT(!(Number{100} <= Number{10}));
1153 }
1154
1155 void
1157 {
1158 testcase << "test_stream " << to_string(Number::getMantissaScale());
1159 Number x{100};
1161 os << x;
1162 BEAST_EXPECT(os.str() == to_string(x));
1163 }
1164
1165 void
1167 {
1168 testcase << "test_inc_dec " << to_string(Number::getMantissaScale());
1169 Number x{100};
1170 Number y = +x;
1171 BEAST_EXPECT(x == y);
1172 BEAST_EXPECT(x++ == y);
1173 BEAST_EXPECT(x == Number{101});
1174 BEAST_EXPECT(x-- == Number{101});
1175 BEAST_EXPECT(x == y);
1176 }
1177
1178 void
1180 {
1181 NumberSO stNumberSO{true};
1182 Issue const issue;
1183 Number const n{7'518'783'80596, -5};
1185 auto res2 = STAmount{issue, n};
1186 BEAST_EXPECT(res2 == STAmount{7518784});
1187
1189 res2 = STAmount{issue, n};
1190 BEAST_EXPECT(res2 == STAmount{7518783});
1191
1193 res2 = STAmount{issue, n};
1194 BEAST_EXPECT(res2 == STAmount{7518783});
1195
1197 res2 = STAmount{issue, n};
1198 BEAST_EXPECT(res2 == STAmount{7518784});
1199 }
1200
1201 void
1203 {
1204 BEAST_EXPECT(Number(25, +1).truncate() == Number(250, 0));
1205 BEAST_EXPECT(Number(25, 0).truncate() == Number(25, 0));
1206 BEAST_EXPECT(Number(25, -1).truncate() == Number(2, 0));
1207 BEAST_EXPECT(Number(25, -2).truncate() == Number(0, 0));
1208 BEAST_EXPECT(Number(99, -2).truncate() == Number(0, 0));
1209
1210 BEAST_EXPECT(Number(-25, +1).truncate() == Number(-250, 0));
1211 BEAST_EXPECT(Number(-25, 0).truncate() == Number(-25, 0));
1212 BEAST_EXPECT(Number(-25, -1).truncate() == Number(-2, 0));
1213 BEAST_EXPECT(Number(-25, -2).truncate() == Number(0, 0));
1214 BEAST_EXPECT(Number(-99, -2).truncate() == Number(0, 0));
1215
1216 BEAST_EXPECT(Number(0, 0).truncate() == Number(0, 0));
1217 BEAST_EXPECT(Number(0, 30000).truncate() == Number(0, 0));
1218 BEAST_EXPECT(Number(0, -30000).truncate() == Number(0, 0));
1219 BEAST_EXPECT(Number(100, -30000).truncate() == Number(0, 0));
1220 BEAST_EXPECT(Number(100, -30000).truncate() == Number(0, 0));
1221 BEAST_EXPECT(Number(-100, -30000).truncate() == Number(0, 0));
1222 BEAST_EXPECT(Number(-100, -30000).truncate() == Number(0, 0));
1223 }
1224
1225 void
1227 {
1228 // Test that rounding works as expected.
1229 testcase("Rounding");
1230
1231 using NumberRoundings = std::map<Number::rounding_mode, std::int64_t>;
1232
1233 std::map<Number, NumberRoundings> const expected{
1234 // Positive numbers
1235 {Number{13, -1},
1237 {Number{23, -1},
1239 {Number{15, -1},
1241 {Number{25, -1},
1243 {Number{152, -2},
1245 {Number{252, -2},
1247 {Number{17, -1},
1249 {Number{27, -1},
1251
1252 // Negative numbers
1253 {Number{-13, -1},
1255 {Number{-23, -1},
1257 {Number{-15, -1},
1259 {Number{-25, -1},
1261 {Number{-152, -2},
1263 {Number{-252, -2},
1265 {Number{-17, -1},
1267 {Number{-27, -1},
1269 };
1270
1271 for (auto const& [num, roundings] : expected)
1272 {
1273 for (auto const& [mode, val] : roundings)
1274 {
1275 NumberRoundModeGuard g{mode};
1276 auto const res = static_cast<std::int64_t>(num);
1277 BEAST_EXPECTS(
1278 res == val,
1279 to_string(num) + " with mode " + std::to_string(mode) + " expected " + std::to_string(val) +
1280 " got " + std::to_string(res));
1281 }
1282 }
1283 }
1284
1285 void
1287 {
1288 auto const scale = Number::getMantissaScale();
1289 testcase << "std::int64_t " << to_string(scale);
1290
1291 // Control case
1292 BEAST_EXPECT(Number::maxMantissa() > 10);
1293 Number ten{10};
1294 BEAST_EXPECT(ten.exponent() <= 0);
1295
1296 if (scale == MantissaRange::small)
1297 {
1299 BEAST_EXPECT(Number::maxMantissa() < INITIAL_XRP.drops());
1300 Number const initalXrp{INITIAL_XRP};
1301 BEAST_EXPECT(initalXrp.exponent() > 0);
1302
1303 Number const maxInt64{Number::maxRep};
1304 BEAST_EXPECT(maxInt64.exponent() > 0);
1305 // 85'070'591'730'234'615'865'843'651'857'942'052'864 - 38 digits
1306 BEAST_EXPECT((power(maxInt64, 2) == Number{85'070'591'730'234'62, 22}));
1307
1308 Number const max = Number{false, Number::maxMantissa(), 0, Number::normalized{}};
1309 BEAST_EXPECT(max.exponent() <= 0);
1310 // 99'999'999'999'999'980'000'000'000'000'001 - 32 digits
1311 BEAST_EXPECT((power(max, 2) == Number{99'999'999'999'999'98, 16}));
1312 }
1313 else
1314 {
1316 BEAST_EXPECT(Number::maxMantissa() > INITIAL_XRP.drops());
1317 Number const initalXrp{INITIAL_XRP};
1318 BEAST_EXPECT(initalXrp.exponent() <= 0);
1319
1320 Number const maxInt64{Number::maxRep};
1321 BEAST_EXPECT(maxInt64.exponent() <= 0);
1322 // 85'070'591'730'234'615'847'396'907'784'232'501'249 - 38 digits
1323 BEAST_EXPECT((power(maxInt64, 2) == Number{85'070'591'730'234'615'85, 19}));
1324
1326
1327 auto const maxMantissa = Number::maxMantissa();
1328 Number const max = Number{false, maxMantissa, 0, Number::normalized{}};
1329 BEAST_EXPECT(max.mantissa() == maxMantissa / 10);
1330 BEAST_EXPECT(max.exponent() == 1);
1331 // 99'999'999'999'999'999'800'000'000'000'000'000'100 - also 38
1332 // digits
1333 BEAST_EXPECT((power(max, 2) == Number{false, maxMantissa / 10 - 1, 20, Number::normalized{}}));
1334 }
1335 }
1336
1337 void
1338 run() override
1339 {
1340 for (auto const scale : {MantissaRange::small, MantissaRange::large})
1341 {
1342 NumberMantissaScaleGuard sg(scale);
1343 testZero();
1344 test_limits();
1345 testToString();
1346 test_add();
1347 test_sub();
1348 test_mul();
1349 test_div();
1350 test_root();
1351 test_root2();
1352 test_power1();
1353 test_power2();
1356 test_squelch();
1358 test_stream();
1359 test_inc_dec();
1361 test_truncate();
1362 testRounding();
1363 testInt64();
1364 }
1365 }
1366};
1367
1368BEAST_DEFINE_TESTSUITE(Number, basics, xrpl);
1369
1370} // namespace xrpl
A testsuite class.
Definition suite.h:51
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:147
bool expect(Condition const &shouldBeTrue)
Evaluate a test condition.
Definition suite.h:221
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:800
RAII class to set and restore the Number switchover.
Definition IOUAmount.h:190
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:401
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:668
static internalrep maxMantissa()
Definition Number.h:407
constexpr int exponent() const noexcept
Returns the exponent of the external view of the Number.
Definition Number.h:563
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:662
static Number lowest() noexcept
Definition Number.h:674
static int mantissaLog()
Definition Number.h:413
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:597
Number root(Number f, unsigned d)
Definition Number.cpp:938
Number power(Number const &f, unsigned n)
Definition Number.cpp:915
static std::int64_t constexpr maxMantissa
Definition IOUAmount.cpp:49
Number root2(Number f)
Definition Number.cpp:1010
constexpr XRPAmount INITIAL_XRP
Configure the native currency.
constexpr Number squelch(Number const &x, Number const &limit) noexcept
Definition Number.h:737
T str(T... args)
T to_string(T... args)