1 /*
2 * Copyright (c) 2020-2024 Stefan Krah. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27
28 #include <climits>
29 #include <cstdint>
30 #include <cstdio>
31 #include <cstdlib>
32 #include <ctime>
33
34 #include <algorithm>
35 #include <array>
36 #include <limits>
37 #include <list>
38 #include <map>
39 #include <random>
40 #include <sstream>
41 #include <string>
42 #include <thread>
43 #include <type_traits>
44 #include <vector>
45
46 #include "mpdecimal.h"
47
48 #include "decimal.hh"
49 #include "test.hh"
50 #include "vctest.hh"
51
52
53 using decimal::Context;
54 using decimal::context_template;
55 using decimal::context;
56
57 using decimal::ROUND_UP;
58 using decimal::ROUND_DOWN;
59 using decimal::ROUND_CEILING;
60 using decimal::ROUND_FLOOR;
61 using decimal::ROUND_HALF_UP;
62 using decimal::ROUND_HALF_DOWN;
63 using decimal::ROUND_HALF_EVEN;
64 using decimal::ROUND_05UP;
65 using decimal::ROUND_TRUNC;
66 using decimal::ROUND_GUARD;
67
68 using decimal::DecIEEEInvalidOperation;
69 using decimal::DecConversionSyntax;
70 using decimal::DecInvalidOperation;
71 using decimal::DecDivisionImpossible;
72 using decimal::DecDivisionUndefined;
73
74 using decimal::DecDivisionByZero;
75 using decimal::DecOverflow;
76 using decimal::DecUnderflow;
77 using decimal::DecSubnormal;
78 using decimal::DecInexact;
79 using decimal::DecRounded;
80 using decimal::DecClamped;
81
82 using decimal::DecMaxStatus;
83
84 using decimal::MaxContext;
85 using decimal::IEEEContext;
86 using decimal::DECIMAL32;
87 using decimal::DECIMAL64;
88 using decimal::DECIMAL128;
89
90 using decimal::DecimalException;
91
92 using decimal::IEEEInvalidOperation;
93 using decimal::ConversionSyntax;
94 using decimal::InvalidOperation;
95 using decimal::DivisionImpossible;
96 using decimal::DivisionUndefined;
97
98 using decimal::DivisionByZero;
99 using decimal::Overflow;
100 using decimal::Underflow;
101 using decimal::Subnormal;
102 using decimal::Inexact;
103 using decimal::Rounded;
104 using decimal::Clamped;
105
106 using decimal::ValueError;
107 using decimal::RuntimeError;
108 using decimal::MallocError;
109
110 using decimal::Decimal;
111
112 using decimal::util::safe_downcast;
113
114 using test::Failure;
115
116
117 /******************************************************************************/
118 /* Default context for some generated test cases */
119 /******************************************************************************/
120
121 static const Context pycontext{ 28, 999999, -999999, ROUND_HALF_EVEN,
122 DecIEEEInvalidOperation | DecDivisionByZero | DecOverflow,
123 0, 0 };
124
125 /******************************************************************************/
126 /* Exception hierarchy */
127 /******************************************************************************/
128
129 static void
ExceptionHierarchyTest()130 ExceptionHierarchyTest()
131 {
132 assertEqual(context, context_template);
133
134 assertTrue((std::is_base_of<std::exception, DecimalException>::value));
135
136 assertTrue((std::is_base_of<DecimalException, IEEEInvalidOperation>::value));
137 assertTrue((std::is_base_of<IEEEInvalidOperation, ConversionSyntax>::value));
138 assertTrue((std::is_base_of<IEEEInvalidOperation, DivisionImpossible>::value));
139 assertTrue((std::is_base_of<IEEEInvalidOperation, DivisionUndefined>::value));
140 assertTrue((std::is_base_of<IEEEInvalidOperation, InvalidOperation>::value));
141
142 assertTrue((std::is_base_of<DecimalException, DivisionByZero>::value));
143 assertTrue((std::is_base_of<DecimalException, Overflow>::value));
144 assertTrue((std::is_base_of<DecimalException, Underflow>::value));
145 assertTrue((std::is_base_of<DecimalException, Subnormal>::value));
146 assertTrue((std::is_base_of<DecimalException, Inexact>::value));
147 assertTrue((std::is_base_of<DecimalException, Rounded>::value));
148 assertTrue((std::is_base_of<DecimalException, Clamped>::value));
149
150 assertTrue((std::is_base_of<std::exception, ValueError>::value));
151 assertTrue((std::is_base_of<std::exception, RuntimeError>::value));
152 assertTrue((std::is_base_of<std::exception, MallocError>::value));
153 }
154
155 /******************************************************************************/
156 /* IEEE interchange contexts */
157 /******************************************************************************/
158
159 static void
IEEEContextTest()160 IEEEContextTest()
161 {
162 assertEqual(context, context_template);
163
164 Context c = IEEEContext(DECIMAL32);
165 assertEqual(c.prec(), 7);
166 assertEqual(c.emax(), 96);
167 assertEqual(c.emin(), -95);
168 assertEqual(c.round(), ROUND_HALF_EVEN);
169 assertEqual(c.traps(), 0U);
170 assertEqual(c.status(), 0U);
171 assertEqual(c.clamp(), 1);
172 assertEqual(c.allcr(), 1);
173 assertEqual(c.etiny(), -101);
174 assertEqual(c.etop(), 90);
175
176 c = IEEEContext(DECIMAL64);
177 assertEqual(c.prec(), 16);
178 assertEqual(c.emax(), 384);
179 assertEqual(c.emin(), -383);
180 assertEqual(c.round(), ROUND_HALF_EVEN);
181 assertEqual(c.traps(), 0U);
182 assertEqual(c.status(), 0U);
183 assertEqual(c.clamp(), 1);
184 assertEqual(c.allcr(), 1);
185 assertEqual(c.etiny(), -398);
186 assertEqual(c.etop(), 369);
187
188 c = IEEEContext(DECIMAL128);
189 assertEqual(c.prec(), 34);
190 assertEqual(c.emax(), 6144);
191 assertEqual(c.emin(), -6143);
192 assertEqual(c.round(), ROUND_HALF_EVEN);
193 assertEqual(c.traps(), 0U);
194 assertEqual(c.status(), 0U);
195 assertEqual(c.clamp(), 1);
196 assertEqual(c.allcr(), 1);
197 assertEqual(c.etiny(), -6176);
198 assertEqual(c.etop(), 6111);
199
200 assertRaises(ValueError, [](){ IEEEContext(-1); });
201 assertRaises(ValueError, [](){ IEEEContext(0); });
202 assertRaises(ValueError, [](){ IEEEContext(16); });
203 assertRaises(ValueError, [](){ IEEEContext(1024); });
204 }
205
206 /******************************************************************************/
207 /* Context get/set */
208 /******************************************************************************/
209
210 static void
ContextGetSetTest()211 ContextGetSetTest()
212 {
213 assertEqual(context, context_template);
214
215 Context c = context;
216
217 c.prec(34);
218 c.emax(3000);
219 c.emin(-3000);
220 c.round(ROUND_HALF_UP);
221 c.traps(DecMaxStatus);
222 c.status(DecMaxStatus);
223 c.clamp(1);
224 c.allcr(0);
225
226 assertEqual(c.prec(), 34);
227 assertEqual(c.emax(), 3000);
228 assertEqual(c.emin(), -3000);
229 assertEqual(c.round(), ROUND_HALF_UP);
230 assertEqual(c.traps(), DecMaxStatus);
231 assertEqual(c.status(), DecMaxStatus);
232 assertEqual(c.clamp(), 1);
233 assertEqual(c.allcr(), 0);
234 assertEqual(c.etiny(), -3033);
235 assertEqual(c.etop(), 2967);
236
237 /* etop is the same, even though it is only relevant for clamp==1 */
238 c.clamp(0);
239 assertEqual(c.etiny(), -3033);
240 assertEqual(c.etop(), 2967);
241
242 c.clear_status(DecDivisionByZero);
243 assertEqual(c.status(), DecMaxStatus & ~DecDivisionByZero);
244
245 c.clear_status();
246 assertEqual(c.status(), 0U);
247
248 c.add_status(DecClamped|DecUnderflow);
249 assertEqual(c.status(), DecClamped|DecUnderflow);
250
251 c.add_status(DecInvalidOperation);
252 assertEqual(c.status(), DecClamped|DecUnderflow|DecInvalidOperation);
253
254 c.clear_traps(DecDivisionUndefined);
255 assertEqual(c.traps(), DecMaxStatus & ~DecDivisionUndefined);
256
257 c.clear_traps();
258 assertEqual(c.traps(), 0U);
259
260 c.add_traps(DecClamped|DecUnderflow);
261 assertEqual(c.traps(), DecClamped|DecUnderflow);
262
263 c.add_traps(DecInvalidOperation);
264 assertEqual(c.traps(), DecClamped|DecUnderflow|DecInvalidOperation);
265 }
266
267
268 /******************************************************************************/
269 /* Context input validation */
270 /******************************************************************************/
271
272 static void
ContextInputValidationTest()273 ContextInputValidationTest()
274 {
275 assertEqual(context, context_template);
276
277 Context c = context;
278
279 /* prec */
280 c.prec(1111);
281 assertEqual(c.prec(), 1111);
282 assertRaises(ValueError, [&](){ c.prec(-1); });
283 assertRaises(ValueError, [&](){ c.prec(MPD_SSIZE_MAX); });
284
285 /* emin */
286 c.emin(-1111);
287 assertEqual(c.emin(), -1111);
288 assertRaises(ValueError, [&](){ c.emin(1); });
289 assertRaises(ValueError, [&](){ c.emin(MPD_SSIZE_MIN); });
290
291 /* emax */
292 c.emax(1111);
293 assertEqual(c.emax(), 1111);
294 assertRaises(ValueError, [&](){ c.emax(-1); });
295 assertRaises(ValueError, [&](){ c.emax(MPD_SSIZE_MAX); });
296
297 /* round */
298 assertRaises(ValueError, [&](){ c.round(-1); });
299 assertRaises(ValueError, [&](){ c.round(ROUND_GUARD); });
300
301 /* traps */
302 assertRaises(ValueError, [&](){ c.traps(DecMaxStatus+1); });
303 assertRaises(ValueError, [&](){ c.traps(UINT32_MAX); });
304
305 /* clamp */
306 assertRaises(ValueError, [&](){ c.clamp(-1); });
307 assertRaises(ValueError, [&](){ c.clamp(2); });
308 assertRaises(ValueError, [&](){ c.clamp(INT_MAX); });
309
310 /* constructor */
311 assertRaises(ValueError, [&](){ Context(1, 1, -1, 999999); });
312 }
313
314 /******************************************************************************/
315 /* Small context */
316 /******************************************************************************/
317
318 static void
SmallContextTest()319 SmallContextTest()
320 {
321 assertEqual(context, context_template);
322
323 Context &c = context;
324
325 Context xc{pycontext};
326 xc.prec(1);
327 xc.emax(1);
328 xc.emin(-1);
329
330 assertEqual(Decimal(9, xc), 9);
331
332 xc.clear_status();
333 assertRaises(ConversionSyntax, [&](){ Decimal("xyz", xc); });
334 assertEqual(xc.status(), DecConversionSyntax);
335 assertEqual(c.status(), 0U);
336
337 xc.clear_status();
338 assertEqual(Decimal(2).exp(xc), 7);
339 assertRaises(Overflow, [&](){ Decimal(8).exp(xc); });
340 assertTrue(xc.status() & DecOverflow);
341 assertEqual(c.status(), 0U);
342
343 xc.clear_status();
344 assertEqual(Decimal(2).ln(xc), Decimal("0.7"));
345 assertRaises(InvalidOperation, [&](){ Decimal(-1).ln(xc); });
346 assertTrue(xc.status() & DecInvalidOperation);
347 assertFalse(c.status() & DecInvalidOperation);
348
349 assertEqual(Decimal(0).log10(xc), Decimal("-inf"));
350 assertEqual(Decimal(-1).next_minus(xc), -2);
351 assertEqual(Decimal(-1).next_plus(xc), Decimal("-0.9"));
352 assertEqual(Decimal("9.73").reduce(xc), Decimal("1E+1"));
353 assertEqual(Decimal("9999").to_integral(xc), 9999);
354 assertEqual(Decimal("-2000").to_integral_exact(xc), -2000);
355 assertEqual(Decimal("0.0625").sqrt(xc), Decimal("0.2"));
356
357 assertEqual(Decimal("0.0625").compare(3, xc), -1);
358
359 xc.clear_status();
360 assertRaises(InvalidOperation, [&](){ Decimal("0").compare_signal(Decimal("nan"), xc); });
361 assertTrue(xc.status() & DecInvalidOperation);
362 assertFalse(c.status() & DecInvalidOperation);
363
364 assertEqual(Decimal("0.01").max(Decimal("0.0101"), xc), Decimal("0.0"));
365 assertEqual(Decimal("0.01").max(Decimal("0.0101"), xc), Decimal("0.0"));
366 assertEqual(Decimal("0.2").max_mag(Decimal("-0.3"), xc),
367 Decimal("-0.3"));
368 assertEqual(Decimal("0.02").min(Decimal("-0.03"), xc), Decimal("-0.0"));
369 assertEqual(Decimal("0.02").min_mag(Decimal("-0.03"), xc),
370 Decimal("0.0"));
371 assertEqual(Decimal("0.2").next_toward(Decimal("-1"), xc), Decimal("0.1"));
372
373 xc.clear_status();
374 assertRaises(InvalidOperation, [&](){ Decimal("0.2").quantize(Decimal("1e10"), xc); });
375 assertTrue(xc.status() & DecInvalidOperation);
376 assertFalse(c.status() & DecInvalidOperation);
377 assertEqual(Decimal("9.99").rem_near(Decimal("1.5"), xc), Decimal("-0.5"));
378
379 assertEqual(Decimal("9.9").fma(7, Decimal("0.9"), xc), Decimal("7E+1"));
380
381 assertFalse(Decimal("0.01").isnormal(xc));
382 assertTrue(Decimal("0.01").issubnormal(xc));
383
384 assertEqual(Decimal(-111).logb(xc), 2);
385 assertEqual(Decimal(0).logical_invert(xc), 1);
386 assertEqual(Decimal("0.01").number_class(xc), std::string("+Subnormal"));
387 assertEqual(Decimal("0.21").to_eng(), "0.21");
388 assertEqual(Decimal("9.99e10").to_eng(), "99.9E+9");
389
390 assertEqual(Decimal("11").logical_and(Decimal("10"), xc), 0);
391 assertEqual(Decimal("11").logical_or(Decimal("10"), xc), 1);
392 assertEqual(Decimal("01").logical_xor(Decimal("10"), xc), 1);
393 assertEqual(Decimal("23").rotate(1, xc), 3);
394 assertEqual(Decimal("23").rotate(1, xc), 3);
395
396 xc.clear_status();
397 assertRaises(Overflow, [&](){ Decimal("23").scaleb(1, xc); });
398 assertTrue(xc.status() & DecOverflow);
399 assertFalse(c.status() & DecOverflow);
400 assertEqual(Decimal("23").shift(-1, xc), 0);
401
402 assertEqual(Decimal(1).canonical(), 1);
403 }
404
405 /******************************************************************************/
406 /* Context representation */
407 /******************************************************************************/
408
409 static void
ContextReprTest()410 ContextReprTest()
411 {
412 assertEqual(context, context_template);
413
414 context.prec(425000000);
415 context.emax(425000000);
416 context.emin(-425000000);
417 context.round(ROUND_HALF_UP);
418 context.clamp(1);
419 context.allcr(1);
420 context.traps(DecMaxStatus);
421 context.status(DecMaxStatus);
422
423 const char *t =
424 "Context(prec=425000000, emax=425000000, emin=-425000000, round=ROUND_HALF_UP, clamp=1, "
425 "traps=[IEEEInvalidOperation, DivisionByZero, Overflow, Underflow, "
426 "Subnormal, Inexact, Rounded, Clamped], "
427 "status=[IEEEInvalidOperation, DivisionByZero, Overflow, Underflow, "
428 "Subnormal, Inexact, Rounded, Clamped])";
429
430 auto s = context.repr();
431 assertEqualStr(s, t);
432
433 s = test::str(context);
434 assertEqualStr(s, t);
435 }
436
437 /******************************************************************************/
438 /* Exact conversions (default) */
439 /******************************************************************************/
440
441 static const char *large_prec[] = {
442 /* int */
443 "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
444 "1234567890123456789012345678901234567890",
445
446 /* negative int */
447 "-12345678901234567890123456789012345678901234567890123456789012345678901234567890"
448 "1234567890123456789012345678901234567890",
449
450 /* float */
451 "1.2345678901234567890123456789012345678901234567890123456789012345678901234567890"
452 "1234567890123456789012345678901234567890E+999999",
453
454 /* negative float */
455 "-1.2345678901234567890123456789012345678901234567890123456789012345678901234567890"
456 "1234567890123456789012345678901234567890E+999999",
457
458 /* tiny float */
459 "1.2345678901234567890123456789012345678901234567890123456789012345678901234567890"
460 "1234567890123456789012345678901234567890E-999999",
461
462 /* negative tiny float */
463 "1.2345678901234567890123456789012345678901234567890123456789012345678901234567890"
464 "1234567890123456789012345678901234567890E-999999",
465
466 /* nan */
467 "NaN12345678901234567890123456789012345678901234567890123456789012345678901234567890"
468 "234567890123456789012345678901234567890",
469
470 /* negative nan */
471 "-NaN12345678901234567890123456789012345678901234567890123456789012345678901234567890"
472 "1234567890123456789012345678901234567890",
473
474 /* snan */
475 "sNaN12345678901234567890123456789012345678901234567890123456789012345678901234567890"
476 "1234567890123456789012345678901234567890",
477
478 /* negative snan */
479 "-sNaN12345678901234567890123456789012345678901234567890123456789012345678901234567890"
480 "1234567890123456789012345678901234567890",
481 };
482
483 template<class T>
484 static void
signed_construction()485 signed_construction()
486 {
487 const T min = std::numeric_limits<T>::min();
488 const T max = std::numeric_limits<T>::max();
489
490 const std::vector<T> values = {min, -1, 0, 1, max};
491 for (const T& v : values) {
492 const Decimal d = {v};
493 const std::string ds = d.to_sci();
494 const std::string vs = std::to_string(v);
495 assertEqual(d, v);
496 assertEqual(v, d);
497 assertEqual(ds, vs);
498 assertEqual(vs, ds);
499 }
500
501 const std::vector<T> signs = {-1, 1};
502 for (int n = 0; n < std::numeric_limits<T>::digits; n++) {
503 for (const T& sign : signs) {
504 for (T x = -5; x < 5; x++) {
505 const T i = static_cast<T>(sign * ((static_cast<T>(1) << n) + x));
506 const Decimal d = {i};
507 assertEqual(d, i);
508 assertEqual(i, d);
509 }
510 }
511 }
512 }
513
514 template<class T>
515 static void
unsigned_construction()516 unsigned_construction()
517 {
518 const T max = std::numeric_limits<T>::max();
519
520 const std::vector<T> values = {0, 1, max};
521 for (const T& v : values) {
522 const Decimal d = {v};
523 const std::string ds = d.to_sci();
524 const std::string vs = std::to_string(v);
525 assertEqual(d, v);
526 assertEqual(v, d);
527 assertEqual(ds, vs);
528 assertEqual(vs, ds);
529 }
530
531 for (int n = 0; n < std::numeric_limits<T>::digits; n++) {
532 for (T x = 0; x < 5; x++) {
533 const T i = static_cast<T>((static_cast<T>(1) << n) + x);
534 const Decimal d = {i};
535 assertEqual(d, i);
536 assertEqual(i, d);
537 }
538 }
539 }
540
541 static void
ExactConstructionTest()542 ExactConstructionTest()
543 {
544 assertEqual(context, context_template);
545
546 context.prec(1);
547 context.emax(1);
548 context.emin(-1);
549 context.traps(DecMaxStatus);
550
551 /*****************************************************************/
552 /* Implicit conversions */
553 /*****************************************************************/
554
555 /* from empty */
556 Decimal empty;
557 assertTrue(empty.issnan());
558
559 /* from const Decimal& */
560 for (auto& s : {"-NaN", "-4096", "4096", "4.5E+3", "Infinity"}) {
561 const Decimal init{Decimal(s)};
562 Decimal x = {init};
563 assertEqualStr(x, s);
564 assertEqualStr(s, x);
565 }
566
567 for (auto& s : large_prec) {
568 const Decimal init{Decimal(s)};
569 Decimal x = {init};
570 assertEqualStr(x, s);
571 assertEqualStr(s, x);
572 }
573
574 /* from Decimal&& */
575 for (auto& s : {"-NaN", "-4096", "4096", "4.5E+3", "Infinity"}) {
576 Decimal init{Decimal(s)};
577 Decimal x = {std::move(init)};
578 assertTrue(init.issnan());
579 assertEqualStr(x, s);
580 assertEqualStr(s, x);
581 }
582
583 for (auto& s : large_prec) {
584 Decimal init{Decimal(s)};
585 Decimal x = {std::move(init)};
586 assertEqualStr(x, s);
587 assertEqualStr(s, x);
588 }
589
590 /* from integers */
591 signed_construction<signed char>();
592 signed_construction<short>();
593 signed_construction<int>();
594 signed_construction<long>();
595 signed_construction<long long>();
596
597 signed_construction<int8_t>();
598 signed_construction<int16_t>();
599 signed_construction<int32_t>();
600 signed_construction<int64_t>();
601
602 unsigned_construction<unsigned char>();
603 unsigned_construction<unsigned short>();
604 unsigned_construction<unsigned int>();
605 unsigned_construction<unsigned long>();
606 unsigned_construction<unsigned long long>();
607
608 unsigned_construction<uint8_t>();
609 unsigned_construction<uint16_t>();
610 unsigned_construction<uint32_t>();
611 unsigned_construction<uint64_t>();
612
613 /*****************************************************************/
614 /* Explicit conversions */
615 /*****************************************************************/
616
617 /* from string */
618 for (auto& s : {"-NaN", "-4096", "4096", "4.5E+3", "Infinity"}) {
619 Decimal x{s};
620 assertEqualStr(x, s);
621 assertEqualStr(s, x);
622 }
623
624 for (auto& s : large_prec) {
625 Decimal x{s};
626 assertEqualStr(x, s);
627 assertEqualStr(s, x);
628 }
629
630 /* from std::string */
631 for (auto& s : {"-sNaN", "123", "1E+999999", "1E-999999"}) {
632 Decimal x{std::string(s)};
633 assertEqualStr(x, s);
634 assertEqualStr(s, x);
635 }
636
637 for (auto& s : large_prec) {
638 Decimal x{std::string(s)};
639 assertEqualStr(x, s);
640 assertEqualStr(s, x);
641 }
642
643 assertEqual(context.status(), 0U);
644
645 /* from string, out of bounds for exact conversion */
646 context.traps(DecInvalidOperation);
647
648 std::string s = std::string("0E") + std::to_string(INT64_MAX);
649 assertRaises(InvalidOperation, [&](){ Decimal x{s}; });
650
651 s = std::string("0E") + std::to_string(INT64_MIN);
652 assertRaises(InvalidOperation, [&](){ Decimal x{s}; });
653
654 s = std::string("1E") + std::to_string(INT64_MAX);
655 assertRaises(InvalidOperation, [&](){ Decimal x{s}; });
656
657 s = std::string("1E") + std::to_string(INT64_MIN);
658 assertRaises(InvalidOperation, [&](){ Decimal x{s}; });
659
660 /* pass explicit context for error reporting */
661 Context c = Context();
662 c.clear_traps();
663 s = std::string("0E") + std::to_string(INT64_MAX);
664 Decimal res = Decimal::exact(s, c);
665 assertEqual(c.status(), DecInvalidOperation);
666
667 /* large values */
668 const char *decstring = "9.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999e425000000";
669 const char *large_exp = "9.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999e99999999999999999999";
670 Decimal large{decstring};
671
672 c.traps(DecMaxStatus-1);
673 c.prec(1);
674
675 Decimal xlarge = Decimal(large);
676 assertEqual(xlarge, large);
677
678 xlarge = Decimal(std::move(large));
679 assertEqual(xlarge, Decimal(decstring));
680 assertTrue(large.issnan());
681
682 assertRaises(InvalidOperation, [&](){ Decimal x = Decimal(large_exp); });
683
684 s = std::string(large_exp);
685 assertRaises(InvalidOperation, [&](){ Decimal x = Decimal(s); });
686
687 context.clear_status();
688 context.clear_traps();
689 }
690
691
692 /******************************************************************************/
693 /* Conversions that respect the context */
694 /******************************************************************************/
695
696 template<class T>
697 static void
signed_construction_ctx(Context & ctx)698 signed_construction_ctx(Context& ctx)
699 {
700 const T min = std::numeric_limits<T>::min();
701 const T max = std::numeric_limits<T>::max();
702
703 for (const T& v : {min, max}) {
704 ctx.clear_traps();
705 ctx.clear_status();
706 const Decimal expected = Decimal(std::to_string(v), ctx);
707 const uint32_t expected_status = ctx.status();
708
709 ctx.clear_status();
710 const Decimal calc = Decimal(v, ctx);
711 const uint32_t calc_status = ctx.status();
712
713 assertEqual(calc, expected);
714 assertEqual(calc_status, expected_status);
715
716 ctx.traps(DecInexact);
717 ctx.clear_status();
718 assertRaises(Inexact, [&](){ Decimal(v, ctx); });
719 assertEqual(ctx.status(), DecInexact|DecRounded);
720 ctx.clear_traps();
721 }
722 }
723
724 template<class T>
725 static void
unsigned_construction_ctx(Context & ctx)726 unsigned_construction_ctx(Context& ctx)
727 {
728 const T v = std::numeric_limits<T>::max();
729 ctx.clear_traps();
730
731 ctx.clear_status();
732 const Decimal expected = Decimal(std::to_string(v), ctx);
733 const uint32_t expected_status = ctx.status();
734
735 ctx.clear_status();
736 const Decimal calc = Decimal(v, ctx);
737 const uint32_t calc_status = ctx.status();
738
739 assertEqual(calc, expected);
740 assertEqual(calc_status, expected_status);
741
742 ctx.traps(DecInexact);
743 ctx.clear_status();
744 assertRaises(Inexact, [&](){ Decimal(v, ctx); });
745 assertEqual(ctx.status(), DecInexact|DecRounded);
746 ctx.clear_traps();
747 }
748
749 static void
InexactConstructionTest()750 InexactConstructionTest()
751 {
752 assertEqual(context, context_template);
753 context.traps(DecMaxStatus);
754
755 Context ctx{context_template};
756 ctx.prec(1);
757 ctx.emax(1);
758 ctx.emin(-1);
759
760 /*****************************************************************/
761 /* Explicit conversions */
762 /*****************************************************************/
763
764 /* from const Decimal& */
765 ctx.clear_traps();
766 ctx.clear_status();
767
768 Decimal nan = Decimal("-NaN123");
769 Decimal integer = Decimal("-4096");
770 Decimal floating = Decimal("4.5E+1");
771
772
773 Decimal x = Decimal(nan, ctx);
774 assertEqualStr(x, "NaN");
775 assertEqual(ctx.status(), DecConversionSyntax);
776
777 ctx.clear_status();
778 x = Decimal(integer, ctx);
779 assertEqualStr(x, "-Infinity");
780 assertEqual(ctx.status(), (DecInexact | DecOverflow | DecRounded));
781
782 ctx.clear_status();
783 x = Decimal(floating, ctx);
784 assertEqualStr(x, "4E+1");
785 assertEqual(ctx.status(), (DecInexact | DecRounded));
786
787 ctx.traps(DecMaxStatus);
788 ctx.clear_status();
789 assertRaises(ConversionSyntax, [&](){ Decimal(nan, ctx); });
790 assertEqual(ctx.status(), DecConversionSyntax);
791
792 ctx.clear_status();
793 assertRaises(Overflow, [&](){ Decimal(integer, ctx); });
794 assertEqual(ctx.status(), (DecInexact | DecOverflow | DecRounded));
795
796 ctx.clear_status();
797 assertRaises(Inexact, [&](){ Decimal(floating, ctx); });
798 assertEqual(ctx.status(), (DecInexact | DecRounded));
799 ctx.clear_traps();
800
801 /* from integers */
802 ctx.prec(1);
803 ctx.emax(19);
804 ctx.emin(-19);
805
806 signed_construction_ctx<signed char>(ctx);
807 signed_construction_ctx<short>(ctx);
808 signed_construction_ctx<int>(ctx);
809 signed_construction_ctx<long>(ctx);
810 signed_construction_ctx<long long>(ctx);
811
812 signed_construction_ctx<int8_t>(ctx);
813 signed_construction_ctx<int16_t>(ctx);
814 signed_construction_ctx<int32_t>(ctx);
815 signed_construction_ctx<int64_t>(ctx);
816
817 unsigned_construction_ctx<unsigned char>(ctx);
818 unsigned_construction_ctx<unsigned short>(ctx);
819 unsigned_construction_ctx<unsigned int>(ctx);
820 unsigned_construction_ctx<unsigned long>(ctx);
821 unsigned_construction_ctx<unsigned long long>(ctx);
822
823 unsigned_construction_ctx<uint8_t>(ctx);
824 unsigned_construction_ctx<uint16_t>(ctx);
825 unsigned_construction_ctx<uint32_t>(ctx);
826 unsigned_construction_ctx<uint64_t>(ctx);
827
828 /* from string */
829 ctx.prec(3);
830 ctx.clear_status();
831 ctx.clear_traps();
832
833 Decimal d = Decimal("456789");
834 assertEqualStr(d, "456789");
835 d = Decimal("456789", ctx);
836 assertEqualStr(d, "4.57E+5");
837
838 ctx.traps(DecInexact);
839 assertRaises(Inexact, [&](){ Decimal("456789", ctx); });
840 ctx.clear_status();
841 ctx.clear_traps();
842
843 ctx.traps(DecRounded);
844 assertRaises(Rounded, [&](){ Decimal("456789", ctx); });
845 ctx.clear_status();
846 ctx.clear_traps();
847
848 ctx.traps(DecConversionSyntax);
849 assertRaises(ConversionSyntax, [&](){ Decimal("NaN12345", ctx); });
850 ctx.clear_status();
851 ctx.clear_traps();
852
853 /* from std::string */
854 d = Decimal(std::string("456789"));
855 assertEqualStr(d, "456789");
856 d = Decimal(std::string("456789"), ctx);
857 assertEqualStr(d, "4.57E+5");
858
859 ctx.traps(DecInexact);
860 assertRaises(Inexact, [&](){ Decimal(std::string("456789"), ctx); });
861 ctx.clear_status();
862 ctx.clear_traps();
863
864 ctx.traps(DecRounded);
865 assertRaises(Rounded, [&](){ Decimal(std::string("456789"), ctx); });
866 ctx.clear_status();
867 ctx.clear_traps();
868
869 ctx.traps(DecConversionSyntax);
870 assertRaises(ConversionSyntax, [&](){ Decimal(std::string("NaN12345"), ctx); });
871
872 #ifndef __mips__ /* miscompilation */
873 /* large values */
874 const char *decstring = "9.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999e425000000";
875 const char *large_exp = "9.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999e99999999999999999999";
876 Decimal large{decstring};
877
878 ctx.traps(DecMaxStatus-1);
879 ctx.prec(100);
880 ctx.emax(425000000);
881 ctx.emin(-425000000);
882
883 Decimal xlarge = Decimal(large, ctx);
884 assertEqual(xlarge, large);
885
886 ctx.prec(1);
887 assertRaises(Overflow, [&](){ Decimal x = Decimal(large_exp, ctx); });
888
889 std::string s = std::string(large_exp);
890 assertRaises(Overflow, [&](){ Decimal x = Decimal(s, ctx); });
891 #endif
892
893 ctx.clear_status();
894 ctx.clear_traps();
895 }
896
897 /******************************************************************************/
898 /* Exceptions during construction */
899 /******************************************************************************/
900
901 static void
ConstructionExceptionTest()902 ConstructionExceptionTest()
903 {
904 assertEqual(context, context_template);
905
906 /*** from string ***/
907
908 /* invalid syntax */
909 context.add_traps(DecConversionSyntax);
910 assertRaises(ConversionSyntax, [](){ Decimal(""); });
911 assertRaises(ConversionSyntax, [](){ Decimal("xyz"); });
912 assertRaises(ConversionSyntax, [](){ Decimal("1 23"); });
913 assertRaises(ConversionSyntax, [](){ Decimal("123\n"); });
914 context.clear_traps(DecConversionSyntax);
915
916 context.add_traps(DecIEEEInvalidOperation);
917 assertRaises(IEEEInvalidOperation, [](){ Decimal("xyz"); });
918 assertRaises(IEEEInvalidOperation, [](){ Decimal("1 23"); });
919 assertRaises(IEEEInvalidOperation, [](){ Decimal("123\n"); });
920 context.clear_traps(DecIEEEInvalidOperation);
921
922 /* too large for exact conversion */
923 context.add_traps(DecInvalidOperation);
924 assertRaises(InvalidOperation, [](){ Decimal("1e9999999999999999999"); });
925 assertRaises(InvalidOperation, [](){ Decimal("-1e9999999999999999999"); });
926 assertRaises(InvalidOperation, [](){ Decimal("1e-9999999999999999999"); });
927 assertRaises(InvalidOperation, [](){ Decimal("-1e-9999999999999999999"); });
928 context.clear_traps(DecInvalidOperation);
929
930 /*** from std::string ***/
931
932 /* invalid syntax */
933 context.add_traps(DecConversionSyntax);
934 assertRaises(ConversionSyntax, [](){ Decimal(std::string("xyz")); });
935 assertRaises(ConversionSyntax, [](){ Decimal(std::string("1 23")); });
936 context.clear_traps(DecConversionSyntax);
937
938 context.add_traps(DecIEEEInvalidOperation);
939 assertRaises(IEEEInvalidOperation, [](){ Decimal(std::string("xyz")); });
940 assertRaises(IEEEInvalidOperation, [](){ Decimal(std::string("1 23")); });
941 context.clear_traps(DecIEEEInvalidOperation);
942
943 /* too large for exact conversion */
944 context.add_traps(DecInvalidOperation);
945 assertRaises(InvalidOperation, [](){ Decimal(std::string("1e9999999999999999999")); });
946 assertRaises(InvalidOperation, [](){ Decimal(std::string("-1e9999999999999999999")); });
947 assertRaises(InvalidOperation, [](){ Decimal(std::string("1e-9999999999999999999")); });
948 assertRaises(InvalidOperation, [](){ Decimal(std::string("-1e-9999999999999999999")); });
949 context.clear_traps(DecInvalidOperation);
950 }
951
952 /******************************************************************************/
953 /* Accessors */
954 /******************************************************************************/
955
956 static void
AccessorTest()957 AccessorTest()
958 {
959 assertEqual(context, context_template);
960
961 Decimal d = Decimal("1.234E+200");
962 assertEqual(d.sign(), 1);
963 assertEqual(d.exponent(), 197);
964 assertEqual(d.coeff(), 1234);
965 assertRaises(ValueError, [&](){ d.payload(); });
966
967 d = Decimal("-1.234E-20");
968 assertEqual(d.sign(), -1);
969 assertEqual(d.exponent(), -23);
970 assertEqual(d.coeff(), 1234);
971 assertRaises(ValueError, [&](){ d.payload(); });
972
973 d = Decimal("inf");
974 assertEqual(d.sign(), 1);
975 assertRaises(ValueError, [&](){ d.exponent(); });
976 assertRaises(ValueError, [&](){ d.coeff(); });
977 assertRaises(ValueError, [&](){ d.payload(); });
978
979 d = Decimal("-inf");
980 assertEqual(d.sign(), -1);
981 assertRaises(ValueError, [&](){ d.exponent(); });
982 assertRaises(ValueError, [&](){ d.coeff(); });
983 assertRaises(ValueError, [&](){ d.payload(); });
984
985 d = Decimal("nan");
986 assertEqual(d.sign(), 1);
987 assertEqual(d.payload(), 0);
988 assertRaises(ValueError, [&](){ d.exponent(); });
989 assertRaises(ValueError, [&](){ d.coeff(); });
990
991 d = Decimal("-nan");
992 assertEqual(d.sign(), -1);
993 assertEqual(d.payload(), 0);
994 assertRaises(ValueError, [&](){ d.exponent(); });
995 assertRaises(ValueError, [&](){ d.coeff(); });
996
997 d = Decimal("snan");
998 assertEqual(d.payload(), 0);
999 assertEqual(d.sign(), 1);
1000 assertRaises(ValueError, [&](){ d.exponent(); });
1001 assertRaises(ValueError, [&](){ d.coeff(); });
1002
1003 d = Decimal("-snan");
1004 assertEqual(d.payload(), 0);
1005 assertEqual(d.sign(), -1);
1006 assertRaises(ValueError, [&](){ d.exponent(); });
1007 assertRaises(ValueError, [&](){ d.coeff(); });
1008
1009 d = Decimal("nan123");
1010 assertEqual(d.sign(), 1);
1011 assertEqual(d.payload(), 123);
1012 assertRaises(ValueError, [&](){ d.exponent(); });
1013 assertRaises(ValueError, [&](){ d.coeff(); });
1014
1015 std::string payload = "123456789123456789123456789123456789123456789123456789123456789123456789"
1016 "123456789123456789123456789123456789123456789123456789123456789123456789";
1017 d = Decimal("-nan" + payload);
1018 assertEqual(d.sign(), -1);
1019 assertEqualStr(d.payload(), payload);
1020 assertRaises(ValueError, [&](){ d.exponent(); });
1021 assertRaises(ValueError, [&](){ d.coeff(); });
1022 }
1023
1024
1025 /******************************************************************************/
1026 /* Assignment operators */
1027 /******************************************************************************/
1028
1029 template <class T>
1030 static void
signed_assignment()1031 signed_assignment()
1032 {
1033 const T min = std::numeric_limits<T>::min();
1034 const T max = std::numeric_limits<T>::max();
1035 const std::vector<T> values = {min, -2, 2, max};
1036
1037 for (const T& v : values) {
1038 Decimal x = v;
1039 assertEqual(x, Decimal(v));
1040
1041 x = Decimal(-10000); x += v;
1042 assertEqual(x, Decimal(-10000) + v);
1043
1044 x = Decimal(2122); x -= v;
1045 assertEqual(x, Decimal(2122) - v);
1046
1047 x = Decimal("1.231e10"); x *= v;
1048 assertEqual(x, Decimal("1.231e10") * v);
1049
1050 x = Decimal("225e-10"); x /= v;
1051 assertEqual(x, Decimal("225e-10") / v);
1052
1053 x = Decimal("25"); x %= v;
1054 assertEqual(x, Decimal("25") % v);
1055 }
1056 }
1057
1058 template <class T>
1059 static void
unsigned_assignment()1060 unsigned_assignment()
1061 {
1062 const T max = std::numeric_limits<T>::max();
1063 const std::vector<T> values = {2, max};
1064
1065 for (const T& v : values) {
1066 Decimal x = v;
1067 assertEqual(x, Decimal(v));
1068
1069 x = Decimal(-10000); x += v;
1070 assertEqual(x, Decimal(-10000) + v);
1071
1072 x = Decimal(2122); x -= v;
1073 assertEqual(x, Decimal(2122) - v);
1074
1075 x = Decimal("1.231e10"); x *= v;
1076 assertEqual(x, Decimal("1.231e10") * v);
1077
1078 x = Decimal("225e-10"); x /= v;
1079 assertEqual(x, Decimal("225e-10") / v);
1080
1081 x = Decimal("25"); x %= v;
1082 assertEqual(x, Decimal("25") % v);
1083 }
1084 }
1085
1086 static void
AssignmentOperatorTest()1087 AssignmentOperatorTest()
1088 {
1089 assertEqual(context, context_template);
1090
1091 /* Decimal */
1092 context.prec(10000);
1093
1094 Decimal x = Decimal(10).pow(1200);
1095 assertEqual(x, Decimal(10).pow(1200));
1096
1097 x = Decimal(10).pow(1200); x += Decimal("1.1127312");
1098 assertEqual(x, Decimal(10).pow(1200) + Decimal("1.1127312"));
1099
1100 x = Decimal(10).pow(1200); x -= Decimal("1.1127312");
1101 assertEqual(x, Decimal(10).pow(1200) - Decimal("1.1127312"));
1102
1103 x = -Decimal(10).pow(1200); x *= Decimal("1.1127312");
1104 assertEqual(x, -Decimal(10).pow(1200) * Decimal("1.1127312"));
1105
1106 x = -Decimal(10).pow(1200); x /= Decimal("1.1127312");
1107 assertEqual(x, -Decimal(10).pow(1200) / Decimal("1.1127312"));
1108
1109 x = Decimal(10).pow(1200); x %= Decimal("1.1127312");
1110 assertEqual(x, Decimal(10).pow(1200) % Decimal("1.1127312"));
1111
1112 /* integers */
1113 context.prec(3);
1114 context.clear_status();
1115
1116 signed_assignment<signed char>();
1117 signed_assignment<short>();
1118 signed_assignment<int>();
1119 signed_assignment<long>();
1120 signed_assignment<long long>();
1121
1122 signed_assignment<int8_t>();
1123 signed_assignment<int16_t>();
1124 signed_assignment<int32_t>();
1125 signed_assignment<int64_t>();
1126
1127 unsigned_assignment<unsigned char>();
1128 unsigned_assignment<unsigned short>();
1129 unsigned_assignment<unsigned int>();
1130 unsigned_assignment<unsigned long>();
1131 unsigned_assignment<unsigned long long>();
1132
1133 unsigned_assignment<uint8_t>();
1134 unsigned_assignment<uint16_t>();
1135 unsigned_assignment<uint32_t>();
1136 unsigned_assignment<uint64_t>();
1137 }
1138
1139 static void
PointerAssignmentOperatorTest()1140 PointerAssignmentOperatorTest()
1141 {
1142 assertEqual(context, context_template);
1143
1144 const Decimal *d = new Decimal;
1145 assertTrue(d->issnan());
1146
1147 const Decimal *x = d;
1148 assertEqual(x, d);
1149
1150 /* CheriBSD: the operator<< overload for uintptr_t is missing (purecap mode) */
1151 #if !defined(__CHERI__)
1152 x += 10;
1153 assertEqual(reinterpret_cast<uintptr_t>(x), reinterpret_cast<uintptr_t>(d) + 10 * (sizeof *d));
1154
1155 x -= 10;
1156 assertEqual(reinterpret_cast<uintptr_t>(x), reinterpret_cast<uintptr_t>(d));
1157 #endif
1158
1159 delete x;
1160 }
1161
1162
1163 /******************************************************************************/
1164 /* Comparison operators */
1165 /******************************************************************************/
1166
1167 template<class T>
1168 static void
signed_comparison()1169 signed_comparison()
1170 {
1171 const T min = std::numeric_limits<T>::min();
1172 const T max = std::numeric_limits<T>::max();
1173 const std::vector<T> values = {min, -1, 0, 1, max};
1174
1175 const Decimal less = Decimal("-1000000000000000000000000000000000");
1176 const Decimal less_equal = Decimal(min);
1177 const Decimal greater_equal = Decimal(max);
1178 const Decimal greater = Decimal("1000000000000000000000000000000000");
1179
1180 for (const T& v : values) {
1181 assertTrue(v == Decimal(v));
1182 assertTrue(Decimal(v) == v);
1183 assertFalse(v != Decimal(v));
1184 assertFalse(Decimal(v) != v);
1185
1186 assertTrue(2 != Decimal(v));
1187 assertTrue(Decimal(v) != 2);
1188 assertFalse(2 == Decimal(v));
1189 assertFalse(Decimal(v) == 2);
1190
1191 assertTrue(v < greater);
1192 assertTrue(less < v);
1193
1194 assertTrue(v <= greater_equal);
1195 assertTrue(less_equal <= v);
1196
1197 assertTrue(v >= less_equal);
1198 assertTrue(greater_equal >= v);
1199
1200 assertTrue(v > less);
1201 assertTrue(greater > v);
1202 }
1203 }
1204
1205 template<class T>
1206 static void
unsigned_comparison()1207 unsigned_comparison()
1208 {
1209 const T max = std::numeric_limits<T>::max();
1210 const std::vector<T> values = {0, 1, max};
1211
1212 Decimal less = Decimal("-1000000000000000000000000000000000");
1213 Decimal less_equal = Decimal(0);
1214 Decimal greater_equal = Decimal(max);
1215 Decimal greater = Decimal("1000000000000000000000000000000000");
1216
1217 for (const T& v : values) {
1218 assertTrue(v == Decimal(v));
1219 assertTrue(Decimal(v) == v);
1220 assertFalse(v != Decimal(v));
1221 assertFalse(Decimal(v) != v);
1222
1223 assertTrue(2 != Decimal(v));
1224 assertTrue(Decimal(v) != 2);
1225 assertFalse(2 == Decimal(v));
1226 assertFalse(Decimal(v) == 2);
1227
1228 assertTrue(v < greater);
1229 assertTrue(less < v);
1230
1231 assertTrue(v <= greater_equal);
1232 assertTrue(less_equal <= v);
1233
1234 assertTrue(v >= less_equal);
1235 assertTrue(greater_equal >= v);
1236
1237 assertTrue(v > less);
1238 assertTrue(greater > v);
1239 }
1240 }
1241
1242 static void
ComparisonOperatorTest()1243 ComparisonOperatorTest()
1244 {
1245 assertEqual(context, context_template);
1246
1247 context.emax(1);
1248 context.emin(-1);
1249 context.clear_status();
1250 context.traps(DecMaxStatus);
1251
1252 /* integer comparisons */
1253 signed_comparison<signed char>();
1254 signed_comparison<short>();
1255 signed_comparison<int>();
1256 signed_comparison<long>();
1257 signed_comparison<long long>();
1258
1259 signed_comparison<int8_t>();
1260 signed_comparison<int16_t>();
1261 signed_comparison<int32_t>();
1262 signed_comparison<int64_t>();
1263
1264 unsigned_comparison<unsigned char>();
1265 unsigned_comparison<unsigned short>();
1266 unsigned_comparison<unsigned int>();
1267 unsigned_comparison<unsigned long>();
1268 unsigned_comparison<unsigned long long>();
1269
1270 unsigned_comparison<uint8_t>();
1271 unsigned_comparison<uint16_t>();
1272 unsigned_comparison<uint32_t>();
1273 unsigned_comparison<uint64_t>();
1274
1275
1276 /* Decimal */
1277 Context ctx = MaxContext();
1278 ctx.traps(DecMaxStatus);
1279 assertTrue(Decimal(10).pow(1200, ctx) == Decimal(10).pow(1200, ctx));
1280 assertTrue(Decimal(10).pow(1201, ctx) != Decimal(10).pow(1200, ctx));
1281 assertTrue(Decimal(10).pow(1200, ctx) < Decimal(10).pow(1201, ctx));
1282 assertTrue(Decimal(10).pow(1200, ctx) <= Decimal(10).pow(1200, ctx));
1283 assertTrue(Decimal(10).pow(1200, ctx) >= Decimal(10).pow(1200, ctx));
1284 assertTrue(Decimal(10).pow(1201, ctx) > Decimal(10).pow(1200, ctx));
1285 assertEqual(ctx.status(), 0U);
1286
1287 /* Decimal NaN */
1288 context.clear_status();
1289 context.traps(DecInvalidOperation);
1290
1291 assertFalse(Decimal("NaN") == 2);
1292 assertFalse(2 == Decimal("NaN"));
1293 assertFalse(Decimal("NaN") == Decimal("NaN"));
1294 assertTrue(Decimal("NaN") != Decimal("NaN"));
1295 assertEqual(context.status(), 0U);
1296
1297 assertRaises(InvalidOperation, [](){ void(Decimal("NaN") < 2); });
1298 assertRaises(InvalidOperation, [](){ void(Decimal("NaN") <= 2); });
1299 assertRaises(InvalidOperation, [](){ void(Decimal("NaN") >= 2); });
1300 assertRaises(InvalidOperation, [](){ void(Decimal("NaN") > 2); });
1301 assertEqual(context.status(), DecInvalidOperation);
1302
1303 /* Decimal sNaN */
1304 context.clear_status();
1305 context.traps(DecInvalidOperation);
1306
1307 assertRaises(InvalidOperation, [](){ void(Decimal("sNaN") == 2); });
1308 assertRaises(InvalidOperation, [](){ void(Decimal("sNaN") != 2); });
1309 assertRaises(InvalidOperation, [](){ void(Decimal("sNaN") < 2); });
1310 assertRaises(InvalidOperation, [](){ void(Decimal("sNaN") <= 2); });
1311 assertRaises(InvalidOperation, [](){ void(Decimal("sNaN") >= 2); });
1312 assertRaises(InvalidOperation, [](){ void(Decimal("sNaN") > 2); });
1313 assertEqual(context.status(), DecInvalidOperation);
1314 }
1315
1316 static void
PointerComparisonOperatorTest()1317 PointerComparisonOperatorTest()
1318 {
1319 assertEqual(context, context_template);
1320
1321 const Decimal *d = new Decimal;
1322 assertTrue(d->issnan());
1323
1324 const Decimal *x = d + 10;
1325 assertFalse(x == d);
1326 assertTrue(x != d);
1327 assertTrue(d < x);
1328 assertTrue(x <= x);
1329 assertTrue(x >= d);
1330 assertTrue(x > d);
1331
1332 delete d;
1333 }
1334
1335 /******************************************************************************/
1336 /* Unary arithmetic operators */
1337 /******************************************************************************/
1338
1339 static void
UnaryOperatorTest()1340 UnaryOperatorTest()
1341 {
1342 assertEqual(context, context_template);
1343
1344 context.prec(3);
1345 assertEqualStr(+Decimal(10000), "1.00E+4");
1346 assertEqualStr(-Decimal(10000), "-1.00E+4");
1347 }
1348
1349 static void
PointerUnaryOperatorTest()1350 PointerUnaryOperatorTest()
1351 {
1352 assertEqual(context, context_template);
1353
1354 context.prec(3);
1355 Decimal *d = new Decimal(10000);
1356
1357 Decimal *x = +d;
1358 assertEqual(x, d);
1359
1360 ++x;
1361 assertEqual(x-1, d);
1362
1363 --x;
1364 assertEqual(x, d);
1365
1366 x++;
1367 assertEqual(x-1, d);
1368
1369 x--;
1370 assertEqual(x, d);
1371
1372 bool b = !x;
1373 assertEqual(b, false);
1374
1375 assertEqual(*x, 10000);
1376 assertEqual(**(&x), 10000);
1377
1378 delete d;
1379 }
1380
1381 /******************************************************************************/
1382 /* Binary arithmetic operators */
1383 /******************************************************************************/
1384
1385 template <class T>
1386 static void
signed_arithmetic()1387 signed_arithmetic()
1388 {
1389 const T min = std::numeric_limits<T>::min();
1390 const T max = std::numeric_limits<T>::max();
1391 const std::vector<T> values = {min, -2, 2, max};
1392
1393 for (const T& v : values) {
1394 assertEqual(Decimal(10) + v, Decimal(10) + Decimal(v));
1395 assertEqual(v + Decimal(10), Decimal(v) + Decimal(10));
1396
1397 assertEqual(Decimal(27) - v, Decimal(27) - Decimal(v));
1398 assertEqual(v - Decimal(27), Decimal(v) - Decimal(27));
1399
1400 assertEqual(Decimal(1729) * v, Decimal(1729) * Decimal(v));
1401 assertEqual(v * Decimal(1729), Decimal(1729) * Decimal(v));
1402
1403 assertEqual(Decimal(225) / v, Decimal(225) / Decimal(v));
1404 assertEqual(v / Decimal(225), Decimal(v) / Decimal(225));
1405
1406 assertEqual(Decimal(15222) % v, Decimal(15222) % Decimal(v));
1407 assertEqual(v % Decimal(15222), Decimal(v) % Decimal(15222));
1408 }
1409 }
1410
1411 template <class T>
1412 static void
unsigned_arithmetic()1413 unsigned_arithmetic()
1414 {
1415 const T max = std::numeric_limits<T>::max();
1416 const std::vector<T> values = {2, max};
1417
1418 for (const T& v : values) {
1419 assertEqual(Decimal(10) + v, Decimal(10) + Decimal(v));
1420 assertEqual(v + Decimal(10), Decimal(v) + Decimal(10));
1421
1422 assertEqual(Decimal(27) - v, Decimal(27) - Decimal(v));
1423 assertEqual(v - Decimal(27), Decimal(v) - Decimal(27));
1424
1425 assertEqual(Decimal(1729) * v, Decimal(1729) * Decimal(v));
1426 assertEqual(v * Decimal(1729), Decimal(1729) * Decimal(v));
1427
1428 assertEqual(Decimal(225) / v, Decimal(225) / Decimal(v));
1429 assertEqual(v / Decimal(225), Decimal(v) / Decimal(225));
1430
1431 assertEqual(Decimal(15222) % v, Decimal(15222) % Decimal(v));
1432 assertEqual(v % Decimal(15222), Decimal(v) % Decimal(15222));
1433 }
1434 }
1435
1436 static void
ArithmeticOperatorTest()1437 ArithmeticOperatorTest()
1438 {
1439 assertEqual(context, context_template);
1440
1441 /* Decimal */
1442 context.prec(9);
1443 assertEqual(Decimal(20) + Decimal(2), 22);
1444 assertEqual(Decimal(5) + 123456789000, Decimal(123456789000));
1445 assertEqual(Decimal(22) - Decimal(2), 20);
1446 assertEqual(Decimal(20) * Decimal(20), 400);
1447 assertEqual(Decimal(10) / Decimal(2), 5);
1448 assertEqual(Decimal(10) % Decimal(3), 1);
1449
1450 /* integers */
1451 context.prec(1000);
1452
1453 signed_arithmetic<signed char>();
1454 signed_arithmetic<short>();
1455 signed_arithmetic<int>();
1456 signed_arithmetic<long>();
1457 signed_arithmetic<long long>();
1458
1459 signed_arithmetic<int8_t>();
1460 signed_arithmetic<int16_t>();
1461 signed_arithmetic<int32_t>();
1462 signed_arithmetic<int64_t>();
1463
1464 unsigned_arithmetic<unsigned char>();
1465 unsigned_arithmetic<unsigned short>();
1466 unsigned_arithmetic<unsigned int>();
1467 unsigned_arithmetic<unsigned long>();
1468 unsigned_arithmetic<unsigned long long>();
1469
1470 unsigned_arithmetic<uint8_t>();
1471 unsigned_arithmetic<uint16_t>();
1472 unsigned_arithmetic<uint32_t>();
1473 unsigned_arithmetic<uint64_t>();
1474 }
1475
1476 static void
PointerArithmeticOperatorTest()1477 PointerArithmeticOperatorTest()
1478 {
1479 assertEqual(context, context_template);
1480
1481 const Decimal *d = new Decimal;
1482 assertTrue(d->issnan());
1483
1484 /* CheriBSD: the operator<< overload for uintptr_t is missing (purecap mode) */
1485 #if !defined(__CHERI__)
1486 const Decimal *x = d + 10;
1487 assertEqual(reinterpret_cast<uintptr_t>(x), reinterpret_cast<uintptr_t>(d) + 10 * (sizeof *d));
1488
1489 x = x - 10;
1490 assertEqual(reinterpret_cast<uintptr_t>(x), reinterpret_cast<uintptr_t>(d));
1491 #endif
1492
1493 delete d;
1494 }
1495
1496 /******************************************************************************/
1497 /* Predicates */
1498 /******************************************************************************/
1499
1500 static void
PredicateTest()1501 PredicateTest()
1502 {
1503 assertEqual(context, context_template);
1504
1505 const Decimal finite("10.1");
1506 const Decimal infinite("-inf");
1507 const Decimal nan("nan");
1508 const Decimal snan("-snan");
1509 const Decimal zero("-0");
1510 const Decimal integer("9.999E+100000");
1511 const Decimal subnormal = Decimal(0).next_plus();
1512
1513 assertTrue(finite.iscanonical());
1514 assertTrue(finite.isfinite());
1515 assertFalse(finite.isinfinite());
1516 assertFalse(finite.isspecial());
1517 assertFalse(finite.isnan());
1518 assertFalse(finite.isqnan());
1519 assertFalse(finite.issnan());
1520 assertFalse(finite.issigned());
1521 assertFalse(finite.iszero());
1522 assertFalse(finite.isinteger());
1523 assertTrue(finite.isnormal());
1524 assertFalse(finite.issubnormal());
1525
1526 assertTrue(infinite.iscanonical());
1527 assertFalse(infinite.isfinite());
1528 assertTrue(infinite.isinfinite());
1529 assertTrue(infinite.isspecial());
1530 assertFalse(infinite.isnan());
1531 assertFalse(infinite.isqnan());
1532 assertFalse(infinite.isqnan());
1533 assertTrue(infinite.issigned());
1534 assertFalse(infinite.iszero());
1535 assertFalse(infinite.isinteger());
1536 assertFalse(infinite.isnormal());
1537 assertFalse(infinite.issubnormal());
1538
1539 assertTrue(nan.iscanonical());
1540 assertFalse(nan.isfinite());
1541 assertFalse(nan.isinfinite());
1542 assertTrue(nan.isspecial());
1543 assertTrue(nan.isnan());
1544 assertTrue(nan.isqnan());
1545 assertFalse(nan.issnan());
1546 assertFalse(nan.issigned());
1547 assertFalse(nan.iszero());
1548 assertFalse(nan.isinteger());
1549 assertFalse(nan.isnormal());
1550 assertFalse(nan.issubnormal());
1551
1552 assertTrue(snan.iscanonical());
1553 assertFalse(snan.isfinite());
1554 assertFalse(snan.isinfinite());
1555 assertTrue(snan.isspecial());
1556 assertTrue(snan.isnan());
1557 assertFalse(snan.isqnan());
1558 assertTrue(snan.issnan());
1559 assertTrue(snan.issigned());
1560 assertFalse(snan.iszero());
1561 assertFalse(snan.isinteger());
1562 assertFalse(snan.isnormal());
1563 assertFalse(snan.issubnormal());
1564
1565 assertTrue(zero.iscanonical());
1566 assertTrue(zero.isfinite());
1567 assertFalse(zero.isinfinite());
1568 assertFalse(zero.isspecial());
1569 assertFalse(zero.isnan());
1570 assertFalse(zero.isqnan());
1571 assertFalse(zero.issnan());
1572 assertTrue(zero.issigned());
1573 assertTrue(zero.iszero());
1574 assertTrue(zero.isinteger());
1575 assertFalse(zero.isnormal());
1576 assertFalse(zero.issubnormal());
1577
1578 assertTrue(integer.iscanonical());
1579 assertTrue(integer.isfinite());
1580 assertFalse(integer.isinfinite());
1581 assertFalse(integer.isspecial());
1582 assertFalse(integer.isnan());
1583 assertFalse(integer.isqnan());
1584 assertFalse(integer.issnan());
1585 assertFalse(integer.issigned());
1586 assertFalse(integer.iszero());
1587 assertTrue(integer.isinteger());
1588 assertTrue(integer.isnormal());
1589 assertFalse(integer.issubnormal());
1590
1591 assertTrue(subnormal.iscanonical());
1592 assertTrue(subnormal.isfinite());
1593 assertFalse(subnormal.isinfinite());
1594 assertFalse(subnormal.isspecial());
1595 assertFalse(subnormal.isnan());
1596 assertFalse(subnormal.isqnan());
1597 assertFalse(subnormal.issnan());
1598 assertFalse(subnormal.issigned());
1599 assertFalse(subnormal.iszero());
1600 assertFalse(subnormal.isinteger());
1601 assertFalse(subnormal.isnormal());
1602 assertTrue(subnormal.issubnormal());
1603
1604 Context ctx{1, 1, -1};
1605 Decimal sub = Decimal("0.00000001");
1606 assertFalse(sub.isnormal(ctx));
1607 assertTrue(sub.issubnormal(ctx));
1608 }
1609
1610 /******************************************************************************/
1611 /* Unary functions */
1612 /******************************************************************************/
1613
1614 static void
UnaryFunctionTest()1615 UnaryFunctionTest()
1616 {
1617 assertEqual(context, context_template);
1618
1619 /* Unary functions, no context arg */
1620 Decimal x = Decimal("-123.113E+25100");
1621
1622 assertEqual(x.adjexp(), 25102);
1623 assertEqual(Decimal("1234e9999").adjexp(), 10002);
1624
1625 assertRaises(ValueError, [](){ Decimal("nan").adjexp(); });
1626 assertRaises(ValueError, [](){ Decimal("inf").adjexp(); });
1627
1628 assertEqual(Decimal::radix(), 10);
1629
1630 assertEqual(x.canonical(), x);
1631
1632 x = Decimal(123456789);
1633 assertEqual(x.copy(), x);
1634
1635 for (const auto& s : large_prec) {
1636 x = Decimal(s);
1637 assertEqualStr(x.copy(), x);
1638 }
1639
1640 x = Decimal(-123456789);
1641 assertEqual(x.copy_abs(), 123456789);
1642
1643 x = Decimal(123456789);
1644 assertEqual(x.copy_negate(), -123456789);
1645
1646 context.prec(10000);
1647 auto large = -Decimal(1172).pow(1712);
1648 assertEqual(large.copy_abs(), -large);
1649 assertEqual(large.copy_negate(), -large);
1650 assertEqual(large.copy_sign(1), -large);
1651 context.prec(9);
1652
1653 /* Unary functions, optional context arg */
1654 Context ctx{1, 1, -1};
1655
1656 assertEqualStr(Decimal("-0.00001").number_class(), "-Normal");
1657 assertEqualStr(Decimal("-0.00001").number_class(ctx), "-Subnormal");
1658
1659 assertEqual(Decimal(-123456789).abs(), 123456789);
1660 assertEqual(Decimal(-15).abs(ctx), Decimal("2E+1"));
1661
1662 assertEqual(Decimal(-1123).exp(), Decimal("1.93774588E-488"));
1663 assertEqual(Decimal(2).exp(ctx), 7);
1664
1665 assertEqual(Decimal(1123).invroot(), Decimal("0.0298407766"));
1666 assertEqual(Decimal(7).invroot(ctx), Decimal("0.4"));
1667
1668 assertEqual(Decimal(0).logical_invert(), Decimal("111111111"));
1669 assertEqual(Decimal(0).logical_invert(ctx), Decimal("1"));
1670
1671 assertEqual(Decimal(10).ln(), Decimal("2.30258509"));
1672 assertEqual(Decimal(10).ln(ctx), Decimal("2"));
1673
1674 assertEqual(Decimal(20).log10(), Decimal("1.30103000"));
1675 assertEqual(Decimal(20).log10(ctx), Decimal("1"));
1676
1677 assertEqual(Decimal("2250000000000000000000000000").logb(), Decimal("27"));
1678 assertEqual(Decimal("2250000000000000000000000000").logb(ctx), Decimal("3E+1"));
1679
1680 assertEqual(Decimal("2250000000000000000000000000").minus(), Decimal("-2.25000000E+27"));
1681 assertEqual(Decimal("25").minus(ctx), Decimal("-2E+1"));
1682
1683 assertEqual(Decimal("2250000000000000000000000000").next_minus(), Decimal("2.24999999E+27"));
1684 assertEqual(Decimal("2250000000000000000000000000").next_minus(ctx), Decimal("9E+1"));
1685
1686 assertEqual(Decimal("2250000000000000000000000000").plus(), Decimal("2.25000000E+27"));
1687 assertEqual(Decimal("28").plus(ctx), Decimal("3E+1"));
1688
1689 assertEqual(Decimal("2250000000000000000000000000").reduce(), Decimal("2.25E+27"));
1690 assertEqual(Decimal("-28").reduce(ctx), Decimal("-3E+1"));
1691
1692 assertEqual(Decimal("22500000.12").to_integral(), Decimal("22500000"));
1693 assertEqual(Decimal("22500000.12").to_integral(ctx), Decimal("22500000"));
1694
1695 assertEqual(Decimal("22500000.12").to_integral_exact(), Decimal("22500000"));
1696 assertEqual(Decimal("22500000.12").to_integral_exact(ctx), Decimal("22500000"));
1697
1698 assertEqual(Decimal("90025").sqrt(), Decimal("300.041664"));
1699 assertEqual(Decimal("99").sqrt(ctx), Decimal("1E+1"));
1700
1701 ctx.round(ROUND_UP);
1702 x = Decimal("99999999999999999999999999.9").to_integral(ctx);
1703 assertEqual(x, Decimal("100000000000000000000000000"));
1704
1705 x = Decimal("99999999999999999999999999.9").to_integral_exact(ctx);
1706 assertEqual(x, Decimal("100000000000000000000000000"));
1707
1708 ctx.add_traps(DecInexact);
1709 assertRaises(Inexact, [&](){ Decimal("999.9").to_integral_exact(ctx); });
1710 }
1711
1712 static void
CeilTest()1713 CeilTest()
1714 {
1715 assertEqual(context, context_template);
1716
1717 context.traps(DecMaxStatus);
1718
1719 const std::vector<std::pair<const char *, long long>> pairs = {
1720 {"123.00", 123},
1721 {"3.2", 4},
1722 {"3.54", 4},
1723 {"3.899", 4},
1724 {"-2.3", -2},
1725 {"-11.0", -11},
1726 {"0.0", 0},
1727 {"-0E3", 0},
1728 {"898211712379812736.1", 898211712379812737LL},
1729 };
1730
1731 for (auto& p : pairs) {
1732 const char *s = p.first;
1733 long long i = p.second;
1734
1735 assertEqual(Decimal(s).ceil(), i);
1736 }
1737
1738 context.status(0);
1739 assertRaises(InvalidOperation, [](){ Decimal("NaN").ceil(); });
1740 assertRaises(InvalidOperation, [](){ Decimal("NaN123").ceil(); });
1741 assertRaises(InvalidOperation, [](){ Decimal("Inf").ceil(); });
1742 assertRaises(InvalidOperation, [](){ Decimal("-Inf").ceil(); });
1743 assertRaises(InvalidOperation, [](){ Decimal("sNaN").ceil(); });
1744 assertEqual(context.status(), DecInvalidOperation);
1745 }
1746
1747 static void
FloorTest()1748 FloorTest()
1749 {
1750 assertEqual(context, context_template);
1751
1752 context.traps(DecMaxStatus);
1753
1754 const std::vector<std::pair<const char *, long long>> pairs = {
1755 {"123.00", 123},
1756 {"3.2", 3},
1757 {"3.54", 3},
1758 {"3.899", 3},
1759 {"-2.3", -3},
1760 {"-11.0", -11},
1761 {"0.0", 0},
1762 {"-0E3", 0},
1763 {"898211712379812736.1", 898211712379812736LL},
1764 };
1765
1766 for (auto& p : pairs) {
1767 const char *s = p.first;
1768 long long i = p.second;
1769
1770 assertEqual(Decimal(s).floor(), i);
1771 }
1772
1773 context.status(0);
1774 assertRaises(InvalidOperation, [](){ Decimal("NaN").floor(); });
1775 assertRaises(InvalidOperation, [](){ Decimal("NaN123").floor(); });
1776 assertRaises(InvalidOperation, [](){ Decimal("Inf").floor(); });
1777 assertRaises(InvalidOperation, [](){ Decimal("-Inf").floor(); });
1778 assertRaises(InvalidOperation, [](){ Decimal("sNaN").floor(); });
1779 assertEqual(context.status(), DecInvalidOperation);
1780 }
1781
1782 static void
TruncTest()1783 TruncTest()
1784 {
1785 assertEqual(context, context_template);
1786
1787 char buf[10];
1788 context.traps(DecMaxStatus);
1789
1790 const std::vector<std::pair<const char *, long long>> pairs = {
1791 {"123.00", 123},
1792 {"3.2", 3},
1793 {"3.54", 3},
1794 {"3.899", 3},
1795 {"-2.3", -2},
1796 {"-11.0", -11},
1797 {"-11.8", -11},
1798 {"0.0", 0},
1799 {"-0E3", 0},
1800 {"898211712379812736.1", 898211712379812736LL},
1801 };
1802
1803 for (auto& p : pairs) {
1804 const char *s = p.first;
1805 long long i = p.second;
1806
1807 assertEqual(Decimal(s).trunc(), i);
1808 }
1809
1810 context.round(ROUND_DOWN);
1811 for (int i = -250; i < 250; i++) {
1812 int n = snprintf(buf, sizeof buf, "%0.2f", i / 100.0);
1813 assertTrue(n >= 0 && n < 10);
1814 Decimal d = Decimal(static_cast<const char *>(buf));
1815 Decimal r = d.to_integral();
1816 assertEqual(d.trunc(), r);
1817 }
1818
1819 context.status(0);
1820 assertRaises(InvalidOperation, [](){ Decimal("NaN").trunc(); });
1821 assertRaises(InvalidOperation, [](){ Decimal("NaN123").trunc(); });
1822 assertRaises(InvalidOperation, [](){ Decimal("Inf").trunc(); });
1823 assertRaises(InvalidOperation, [](){ Decimal("-Inf").trunc(); });
1824 assertRaises(InvalidOperation, [](){ Decimal("sNaN").trunc(); });
1825 assertEqual(context.status(), DecInvalidOperation);
1826 }
1827
1828 /******************************************************************************/
1829 /* Binary functions */
1830 /******************************************************************************/
1831
1832 static void
BinaryFunctionTest()1833 BinaryFunctionTest()
1834 {
1835 assertEqual(context, context_template);
1836
1837 /* Binary functions, no context arg */
1838 assertEqual(Decimal("123").compare_total(Decimal("sNaN")), Decimal("-1"));
1839 assertEqual(Decimal("-123").compare_total_mag(Decimal("10")), Decimal("1"));
1840
1841 /* Binary functions */
1842 Context ctx{3, 100, -100};
1843 ctx.round(ROUND_UP);
1844 ctx.clamp(1);
1845 ctx.traps(DecIEEEInvalidOperation);
1846
1847 assertEqualStr(Decimal(1234567890).add(Decimal("-9988888.23")), "1.22457900E+9");
1848 assertEqualStr(Decimal(1234567890).add(Decimal("-9988888.23"), ctx), "1.23E+9");
1849
1850 assertEqualStr(Decimal(1234567890).div(Decimal("-9988888.23")), "-123.594124");
1851 assertEqualStr(Decimal(1234567890).div(Decimal("-9988888.23"), ctx), "-124");
1852
1853 assertEqualStr(Decimal(1234567890).divint(Decimal("-9988888.23")), "-123");
1854 assertEqualStr(Decimal(1234567890).divint(Decimal("-9988888.23"), ctx), "-123");
1855
1856 assertEqualStr(Decimal(1234567890).compare(Decimal("-9988888.23")), 1);
1857 assertEqualStr(Decimal(1234567890).compare(Decimal("-9988888.23"), ctx), 1);
1858
1859 assertEqualStr(Decimal(1234567890).compare_signal(Decimal("-9988888.23")), 1);
1860 assertEqualStr(Decimal(1234567890).compare_signal(Decimal("-9988888.23"), ctx), 1);
1861
1862 assertEqualStr(Decimal("101111").logical_and(Decimal("110001101")), "1101");
1863 assertEqualStr(Decimal("101111").logical_and(Decimal("110001101"), ctx), "101");
1864
1865 assertEqualStr(Decimal("101111").logical_or(Decimal("110001101")), "110101111");
1866 assertEqualStr(Decimal("101111").logical_or(Decimal("110001101"), ctx), "111");
1867
1868 assertEqualStr(Decimal("101111").logical_xor(Decimal("110001101")), "110100010");
1869 assertEqualStr(Decimal("101111").logical_xor(Decimal("110001101"), ctx), "10");
1870
1871 assertEqualStr(Decimal(1234567890).max(Decimal("-9988888.23")), "1.23456789E+9");
1872 assertEqualStr(Decimal(1234567890).max(Decimal("-9988888.23"), ctx), "1.24E+9");
1873
1874 assertEqualStr(Decimal(1234567890).max_mag(Decimal("-9988888.23")), "1.23456789E+9");
1875 assertEqualStr(Decimal(1234567890).max_mag(Decimal("-9988888.23"), ctx), "1.24E+9");
1876
1877 assertEqualStr(Decimal(1234567890).min(Decimal("-9988888.23")), "-9988888.23");
1878 assertEqualStr(Decimal(1234567890).min(Decimal("-9988888.23"), ctx), "-9.99E+6");
1879
1880 assertEqualStr(Decimal(1234567890).min_mag(Decimal("-9988888.23")), "-9988888.23");
1881 assertEqualStr(Decimal(1234567890).min_mag(Decimal("-9988888.23"), ctx), "-9.99E+6");
1882
1883 assertEqualStr(Decimal(1234567890).mul(Decimal("-9988888.23")), "-1.23319607E+16");
1884 assertEqualStr(Decimal(1234567890).mul(Decimal("-9988888.23"), ctx), "-1.24E+16");
1885
1886 assertEqualStr(Decimal(1234567890).next_toward(Decimal("-9988888.23")), "1.23456788E+9");
1887 assertEqualStr(Decimal(1234567890).next_toward(Decimal("-9988888.23"), ctx), "1.23E+9");
1888
1889 assertEqualStr(Decimal(1234567890).pow(Decimal("-9988888.23")), "0E-1000007");
1890 assertEqualStr(Decimal(1234567890).pow(Decimal("-9988888.23"), ctx), "1E-102");
1891 ctx.clear_status();
1892 assertEqual(Decimal("1.0").pow(100, ctx), Decimal("1.00"));
1893 assertTrue(ctx.status() & DecRounded);
1894 ctx.clear_status();
1895 ctx.emax(1);
1896 ctx.emin(-1);
1897 assertEqual(Decimal(10000).pow(Decimal("0.5"), ctx), Decimal("inf"));
1898 assertTrue(ctx.status() & DecOverflow);
1899 ctx.emax(100);
1900 ctx.emin(-100);
1901
1902 assertEqualStr(Decimal(1234567890).rem(Decimal("-9988888.23")), "5934637.71");
1903 assertEqualStr(Decimal(1234567890).rem(Decimal("-9988888.23"), ctx), "5.94E+6");
1904
1905 assertEqualStr(Decimal(1234567890).rem_near(Decimal("-9988888.23")), "-4054250.52");
1906 assertEqualStr(Decimal(1234567890).rem_near(Decimal("-9988888.23"), ctx), "-4.06E+6");
1907
1908 assertEqualStr(Decimal(1234567890).rotate(2), "456789023");
1909 assertEqualStr(Decimal(1234567890).rotate(2, ctx), "89");
1910
1911 assertEqualStr(Decimal(20).quantize(Decimal("1E-2")), "20.00");
1912 assertRaises(InvalidOperation, [&](){ Decimal(20).quantize(Decimal("1E-2"), ctx); });
1913 assertEqualStr(Decimal(20).quantize(Decimal("1E-1"), ctx), "20.0");
1914
1915 assertEqualStr(Decimal(20).scaleb(Decimal("100")), "2.0E+101");
1916 ctx.add_traps(DecOverflow);
1917 assertRaises(Overflow, [&](){ Decimal(20).scaleb(Decimal("100"), ctx); });
1918 assertEqualStr(Decimal(20).scaleb(Decimal("10"), ctx), "2.0E+11");
1919
1920 assertEqualStr(Decimal(1).shift(8), Decimal("100000000"));
1921 assertRaises(InvalidOperation, [&](){ Decimal(1).shift(8, ctx); });
1922 assertEqualStr(Decimal(1).shift(2, ctx), 100);
1923
1924 assertEqualStr(Decimal(1234567890).sub(Decimal("-9988888.23")), "1.24455678E+9");
1925 assertEqualStr(Decimal(1234567890).sub(Decimal("-9988888.23"), ctx), "1.25E+9");
1926 }
1927
1928 /******************************************************************************/
1929 /* Divmod */
1930 /******************************************************************************/
1931
1932 static void
DivmodTest()1933 DivmodTest()
1934 {
1935 assertEqual(context, context_template);
1936
1937 /* Binary functions */
1938 Context ctx{3, 100, -100};
1939 ctx.round(ROUND_UP);
1940 ctx.clamp(1);
1941 ctx.traps(DecIEEEInvalidOperation);
1942
1943 auto result = Decimal("1234567890").divmod(12716);
1944 assertEqual(result.first, 97087);
1945 assertEqual(result.second, 9598);
1946
1947 assertRaises(DivisionImpossible, [&](){ Decimal("1234567890").divmod(12716, ctx); });
1948
1949 result = Decimal("1234567890").divmod(12716172);
1950 assertEqualStr(result.first, "97");
1951 assertEqualStr(result.second, "1099206");
1952
1953 result = Decimal("10912837129").divmod(1001);
1954 assertEqual(result.first, Decimal("10901935"));
1955 assertEqual(result.second, Decimal("194"));
1956
1957 result = Decimal("NaN").divmod(7);
1958 assertTrue(result.first.isqnan());
1959 assertTrue(result.second.isqnan());
1960
1961 context.clear_traps();
1962 context.clear_status();
1963 result = Decimal("inf").divmod(Decimal("inf"));
1964 assertTrue(result.first.isqnan());
1965 assertTrue(result.second.isqnan());
1966 assertTrue(context.status() & DecInvalidOperation);
1967
1968 context.clear_status();
1969 result = Decimal("inf").divmod(Decimal("101"));
1970 assertTrue(result.first.isinfinite());
1971 assertTrue(result.second.isqnan());
1972 assertTrue(context.status() & DecInvalidOperation);
1973
1974 context.clear_status();
1975 result = Decimal("0").divmod(Decimal("0"));
1976 assertTrue(result.first.isqnan());
1977 assertTrue(result.second.isqnan());
1978 assertTrue(context.status() & DecDivisionUndefined);
1979
1980 context.clear_status();
1981 result = Decimal("11").divmod(Decimal("0"));
1982 assertTrue(result.first.isinfinite());
1983 assertTrue(result.second.isqnan());
1984 assertTrue(context.status() & DecInvalidOperation);
1985 assertTrue(context.status() & DecDivisionByZero);
1986 }
1987
1988 /******************************************************************************/
1989 /* Quantize */
1990 /******************************************************************************/
1991
1992 static void
QuantizeTest()1993 QuantizeTest()
1994 {
1995 assertEqual(context, context_template);
1996
1997 context.clear_status();
1998
1999 Context c = Context(9, 99999, -99999, ROUND_DOWN);
2000 assertEqual(Decimal("7.335").quantize(Decimal(".01")), Decimal("7.34"));
2001 assertEqual(Decimal("7.335").quantize(Decimal(".01"), c), Decimal("7.33"));
2002
2003 c = Context(28, 99999, -99999);
2004 c.traps(DecInvalidOperation);
2005 assertRaises(InvalidOperation, [&](){ Decimal("10e99999").quantize(Decimal("1e100000"), c); });
2006
2007 c = Context();
2008 c.round(ROUND_DOWN);
2009 Decimal d = Decimal("0.871831e800");
2010 Decimal x = d.quantize(Decimal("1e797"), c);
2011 assertEqual(x, Decimal("8.71E+799"));
2012 }
2013
2014 /******************************************************************************/
2015 /* Ternary functions */
2016 /******************************************************************************/
2017
2018 static void
TernaryFunctionTest()2019 TernaryFunctionTest()
2020 {
2021 assertEqual(context, context_template);
2022
2023 Context ctx{3, 100, -100};
2024 ctx.round(ROUND_UP);
2025 ctx.clamp(1);
2026 ctx.traps(DecIEEEInvalidOperation);
2027
2028 assertEqual(Decimal("1234").fma(919, Decimal("3.2507355")), Decimal("1134049.25"));
2029 assertEqual(Decimal("1234").fma(919, Decimal("3.2507355"), ctx), Decimal("1.14E+6"));
2030
2031 assertEqual(Decimal("1234").powmod(919, Decimal("123456789")), Decimal("119347714"));
2032 assertRaises(InvalidOperation, [&](){ Decimal("1234").powmod(919, Decimal("123456789"), ctx); });
2033 assertEqual(Decimal("1234").powmod(919, Decimal("996")), Decimal("892"));
2034
2035 ctx.prec(2);
2036 assertRaises(InvalidOperation, [&](){ Decimal("1000").powmod(1, Decimal("501"), ctx); });
2037 }
2038
2039 /******************************************************************************/
2040 /* Irregular functions */
2041 /******************************************************************************/
2042
2043 static void
IrregularFunctionTest()2044 IrregularFunctionTest()
2045 {
2046 assertEqual(context, context_template);
2047
2048 Context ctx{3, 100, -100};
2049 ctx.round(ROUND_UP);
2050 ctx.clamp(1);
2051 ctx.traps(DecIEEEInvalidOperation);
2052
2053 assertEqual(Decimal("1").cmp(10), -1);
2054 assertEqual(Decimal("10").cmp(10), 0);
2055 assertEqual(Decimal("10").cmp(1), 1);
2056 assertEqual(Decimal("1").cmp(Decimal("inf")), -1);
2057 assertEqual(Decimal("1").cmp(Decimal("-inf")), 1);
2058 assertEqual(Decimal("inf").cmp(Decimal("1")), 1);
2059 assertEqual(Decimal("-inf").cmp(Decimal("1")), -1);
2060 assertEqual(Decimal("-inf").cmp(Decimal("inf")), -1);
2061 assertEqual(Decimal("inf").cmp(Decimal("-inf")), 1);
2062 assertEqual(Decimal("10").cmp(Decimal("nan")), INT_MAX);
2063 assertEqual(Decimal("inf").cmp(Decimal("nan")), INT_MAX);
2064 assertEqual(Decimal("nan").cmp(Decimal("nan")), INT_MAX);
2065 assertEqual(Decimal("nan").cmp(Decimal("snan")), INT_MAX);
2066 assertEqual(Decimal("snan").cmp(Decimal("snan")), INT_MAX);
2067
2068 assertEqual(Decimal("1").cmp_total(10), -1);
2069 assertEqual(Decimal("10").cmp_total(10), 0);
2070 assertEqual(Decimal("10").cmp_total(1), 1);
2071 assertEqual(Decimal("1").cmp_total(Decimal("inf")), -1);
2072 assertEqual(Decimal("1").cmp_total(Decimal("-inf")), 1);
2073 assertEqual(Decimal("inf").cmp_total(Decimal("1")), 1);
2074 assertEqual(Decimal("-inf").cmp_total(Decimal("1")), -1);
2075 assertEqual(Decimal("-inf").cmp_total(Decimal("inf")), -1);
2076 assertEqual(Decimal("inf").cmp_total(Decimal("-inf")), 1);
2077 assertEqual(Decimal("10").cmp_total(Decimal("nan")), -1);
2078 assertEqual(Decimal("inf").cmp_total(Decimal("nan")), -1);
2079 assertEqual(Decimal("nan").cmp_total(Decimal("inf")), 1);
2080 assertEqual(Decimal("nan").cmp_total(Decimal("nan")), 0);
2081 assertEqual(Decimal("nan").cmp_total(Decimal("snan")), 1);
2082 assertEqual(Decimal("snan").cmp_total(Decimal("snan")), 0);
2083
2084 assertEqual(Decimal("1").compare_total_mag(10), -1);
2085 assertEqual(Decimal("-10").compare_total_mag(1), 1);
2086 assertEqual(Decimal("10").compare_total_mag(1), 1);
2087 assertEqual(Decimal("1").compare_total_mag(Decimal("inf")), -1);
2088 assertEqual(Decimal("1").compare_total_mag(Decimal("-inf")), -1);
2089 assertEqual(Decimal("inf").compare_total_mag(Decimal("1")), 1);
2090 assertEqual(Decimal("-inf").compare_total_mag(Decimal("1")), 1);
2091 assertEqual(Decimal("-inf").compare_total_mag(Decimal("inf")), 0);
2092 assertEqual(Decimal("inf").compare_total_mag(Decimal("-inf")), 0);
2093 assertEqual(Decimal("10").compare_total_mag(Decimal("nan")), -1);
2094 assertEqual(Decimal("inf").compare_total_mag(Decimal("nan")), -1);
2095 assertEqual(Decimal("nan").compare_total_mag(Decimal("inf")), 1);
2096 assertEqual(Decimal("nan").compare_total_mag(Decimal("nan")), 0);
2097 assertEqual(Decimal("nan").compare_total_mag(Decimal("snan")), 1);
2098 assertEqual(Decimal("snan").compare_total_mag(Decimal("snan")), 0);
2099
2100 assertEqual(Decimal("10").copy_sign(-1), -10);
2101
2102 ctx.round(ROUND_DOWN);
2103 assertEqual(Decimal("123456785").rescale(1, ctx), Decimal("1.2345678E+8"));
2104 ctx.round(ROUND_UP);
2105 assertEqual(Decimal("123456785").rescale(1, ctx), Decimal("1.2345679E+8"));
2106
2107 assertTrue(Decimal("123456785").same_quantum(10));
2108 assertFalse(Decimal("123456785").same_quantum(Decimal("1E+1")));
2109
2110 assertEqual(Decimal("1").shiftn(8), Decimal("1E+8"));
2111 assertRaises(InvalidOperation, [&](){ Decimal("1").shiftn(8, ctx); });
2112 assertEqual(Decimal("1000").shiftn(-1), Decimal("100"));
2113
2114 assertEqual(Decimal("1").shiftl(100), Decimal("1E+100"));
2115 assertEqual(Decimal("1").shiftl(100, ctx), Decimal("1E+100"));
2116 assertRaises(ValueError, [](){ Decimal("NaN").shiftl(100); });
2117 assertRaises(ValueError, [](){ Decimal("sNaN").shiftl(100); });
2118 assertRaises(ValueError, [](){ Decimal("Infinity").shiftl(100); });
2119
2120 assertEqual(Decimal("1000000000000").shiftr(1), Decimal("100000000000"));
2121 assertEqual(Decimal("1000000000000").shiftr(1, ctx), Decimal("100000000000"));
2122 assertRaises(ValueError, [](){ Decimal("NaN").shiftl(100); });
2123 assertRaises(ValueError, [](){ Decimal("sNaN").shiftl(100); });
2124 assertRaises(ValueError, [](){ Decimal("Infinity").shiftl(100); });
2125
2126 assertEqual(Decimal::ln10(9), Decimal("2.30258509"));
2127 }
2128
2129 /******************************************************************************/
2130 /* Apply */
2131 /******************************************************************************/
2132
2133 static void
ApplyTest()2134 ApplyTest()
2135 {
2136 assertEqual(context, context_template);
2137
2138 context.prec(2);
2139
2140 Decimal d = Decimal("1.234E+200");
2141 assertEqual(+d, Decimal("1.2E+200"));
2142 assertEqual(d.apply(context), Decimal("1.2E+200"));
2143 assertEqual(Decimal("1.2E+200", context), Decimal("1.2E+200"));
2144
2145 d = Decimal("-0");
2146 assertEqualStr(+d, "0");
2147 assertEqualStr(d.apply(context), "-0");
2148 assertEqualStr(Decimal("-0", context), "-0");
2149
2150 d = Decimal("NaN0123456789");
2151 assertEqualStr(+d, "NaN89");
2152 assertEqualStr(d.apply(context), "NaN89");
2153 assertEqualStr(Decimal(d, context), "NaN");
2154
2155 context.add_traps(DecIEEEInvalidOperation);
2156 assertRaises(ConversionSyntax, [&](){ Decimal(d, context); });
2157 }
2158
2159 /******************************************************************************/
2160 /* Integer conversion */
2161 /******************************************************************************/
2162
2163 static void
IntegerConversionTest()2164 IntegerConversionTest()
2165 {
2166 assertEqual(context, context_template);
2167
2168 assertEqual(Decimal(INT64_MIN).i64(), INT64_MIN);
2169 assertEqual(Decimal(INT64_MAX).i64(), INT64_MAX);
2170 assertEqual(Decimal("1E+3").i64(), 1000);
2171 assertRaises(ValueError, [](){ Decimal("1E+20").i64(); });
2172 assertRaises(ValueError, [](){ Decimal("-1E+20").i64(); });
2173 assertRaises(ValueError, [](){ Decimal("1E-20").i64(); });
2174 assertRaises(ValueError, [](){ Decimal("nan").i64(); });
2175 assertRaises(ValueError, [](){ Decimal("inf").i64(); });
2176
2177 assertEqual(Decimal(INT32_MIN).i32(), INT32_MIN);
2178 assertEqual(Decimal(INT32_MAX).i32(), INT32_MAX);
2179 assertEqual(Decimal("1E+3").i32(), 1000);
2180 assertRaises(ValueError, [](){ Decimal("1E+11").i32(); });
2181 assertRaises(ValueError, [](){ Decimal("-1E+11").i32(); });
2182 assertRaises(ValueError, [](){ Decimal("1E-11").i32(); });
2183 assertRaises(ValueError, [](){ Decimal("nan").i32(); });
2184 assertRaises(ValueError, [](){ Decimal("inf").i32(); });
2185
2186 assertEqual(Decimal(UINT64_MAX).u64(), UINT64_MAX);
2187 assertEqual(Decimal("1E+3").u64(), 1000U);
2188 assertRaises(ValueError, [](){ Decimal("-1").u64(); });
2189 assertRaises(ValueError, [](){ Decimal("1E+20").u64(); });
2190 assertRaises(ValueError, [](){ Decimal("-1E+20").u64(); });
2191 assertRaises(ValueError, [](){ Decimal("1E-20").u64(); });
2192 assertRaises(ValueError, [](){ Decimal("nan").u64(); });
2193 assertRaises(ValueError, [](){ Decimal("inf").u64(); });
2194
2195 assertEqual(Decimal(UINT32_MAX).u32(), UINT32_MAX);
2196 assertEqual(Decimal("1E+3").u32(), 1000U);
2197 assertRaises(ValueError, [](){ Decimal("-1").u32(); });
2198 assertRaises(ValueError, [](){ Decimal("1E+11").u32(); });
2199 assertRaises(ValueError, [](){ Decimal("-1E+11").u32(); });
2200 assertRaises(ValueError, [](){ Decimal("1E-11").u32(); });
2201 assertRaises(ValueError, [](){ Decimal("nan").u32(); });
2202 assertRaises(ValueError, [](){ Decimal("inf").u32(); });
2203 }
2204
2205 /******************************************************************************/
2206 /* Exact arithmetic */
2207 /******************************************************************************/
2208
2209 static void
ExactArithTest()2210 ExactArithTest()
2211 {
2212 assertEqual(context, context_template);
2213
2214 context = MaxContext();
2215
2216 assertEqual(Decimal(0).exp(), 1);
2217 assertEqual(Decimal(1).ln(), 0);
2218 assertEqual(Decimal(1).log10(), 0);
2219 assertEqual(Decimal(100).log10(), 2);
2220 assertEqual(Decimal("1E+223").log10(), 223);
2221 assertEqual(Decimal("1E+19").logb(), 19);
2222 assertEqual(Decimal(4).sqrt(), 2);
2223 assertEqual(Decimal("40E+9").sqrt(), Decimal("2.0E+5"));
2224 assertEqual(Decimal(10).divint(3), 3);
2225 assertEqual(Decimal(4) / 2, 2);
2226 assertEqual(Decimal(400).pow(-1), Decimal("0.0025"));
2227 }
2228
2229 /******************************************************************************/
2230 /* Containers and data structures */
2231 /******************************************************************************/
2232
2233 static void
DataStructuresTest(void)2234 DataStructuresTest(void)
2235 {
2236 assertEqual(context, context_template);
2237
2238 /* array */
2239 Decimal *x = new Decimal[10]();
2240
2241 for (size_t i = 0; i < 10; i++) {
2242 assertTrue(x[i].issnan());
2243 x[i] = i;
2244 }
2245 for (size_t i = 0; i < 10; i++) {
2246 assertEqual(x[i], i);
2247 }
2248
2249 delete[] x;
2250
2251 /* array of pointers */
2252 Decimal **y = new Decimal *[10];
2253
2254 for (size_t i = 0; i < 10; i++) {
2255 y[i] = new Decimal();
2256 assertTrue((*y[i]).issnan());
2257 *y[i] = i;
2258 }
2259 for (size_t i = 0; i < 10; i++) {
2260 assertEqual(*y[i], i);
2261 }
2262 for (size_t i = 0; i < 10; i++) {
2263 delete y[i];
2264 }
2265
2266 delete[] y;
2267
2268 /* linked list */
2269 std::list<Decimal> lst;
2270
2271 for (size_t i = 0; i < 10; i++) {
2272 lst.push_front(Decimal(i));
2273 }
2274 lst.sort();
2275 size_t n = 0;
2276 for (const Decimal& d : lst) {
2277 assertEqual(d, n++);
2278 }
2279
2280 /* map */
2281 std::map<const char *, Decimal> map1;
2282 std::vector<const char *> keys = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
2283
2284 for (auto& k : keys) {
2285 map1[k] = Decimal(k);
2286 }
2287 for (auto& k : keys) {
2288 assertEqual(map1.at(k), Decimal(k));
2289 }
2290
2291 /* map */
2292 std::map<Decimal, const char *> map2;
2293 std::vector<const char *> values = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
2294
2295 for (auto& v : values) {
2296 map2[Decimal(v)] = v;
2297 }
2298
2299 for (auto& v : values) {
2300 assertEqual(map2.at(Decimal(v)), v);
2301 }
2302 }
2303
2304 static void
LargeDataStructuresTest(void)2305 LargeDataStructuresTest(void)
2306 {
2307 assertEqual(context, context_template);
2308
2309 std::vector<Decimal> powers(10);
2310
2311 context.prec(10000);
2312 context.traps(DecMaxStatus);
2313
2314 for (size_t i = 0; i < 10; i++) {
2315 powers[i] = Decimal(i).pow(2100);
2316 }
2317
2318 /* array */
2319 Decimal *x = new Decimal[10]();
2320
2321 for (size_t i = 0; i < 10; i++) {
2322 assertTrue(x[i].issnan());
2323 x[i] = powers[i];
2324 }
2325 for (size_t i = 0; i < 10; i++) {
2326 assertEqual(x[i], powers[i]);
2327 }
2328
2329 delete[] x;
2330
2331 /* array of pointers */
2332 Decimal **y = new Decimal *[10];
2333
2334 for (size_t i = 0; i < 10; i++) {
2335 y[i] = new Decimal();
2336 assertTrue((*y[i]).issnan());
2337 *y[i] = powers[i];
2338 }
2339 for (size_t i = 0; i < 10; i++) {
2340 assertEqual(*y[i], powers[i]);
2341 }
2342 for (size_t i = 0; i < 10; i++) {
2343 delete y[i];
2344 }
2345
2346 delete[] y;
2347
2348 /* linked list */
2349 std::list<Decimal> lst;
2350
2351 for (size_t i = 0; i < 10; i++) {
2352 lst.push_front(powers[i]);
2353 }
2354 lst.sort();
2355 size_t n = 0;
2356 for (const Decimal& d : lst) {
2357 assertEqual(d, powers[n++]);
2358 }
2359
2360 /* map */
2361 std::map<const char *, Decimal> map1;
2362 std::vector<const char *> keys = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
2363
2364 for (size_t i = 0; i < 10; i++) {
2365 map1[keys[i]] = powers[i];
2366 }
2367
2368 for (size_t i = 0; i < 10; i++) {
2369 assertEqual(map1.at(keys[i]), powers[i]);
2370 }
2371
2372 std::map<Decimal, Decimal> map2;
2373 std::vector<const char *> values = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
2374
2375 for (size_t i = 0; i < 10; i++) {
2376 map2[Decimal(values[i])] = powers[i];
2377 }
2378
2379 for (size_t i = 0; i < 10; i++) {
2380 assertEqual(map2.at(Decimal(values[i])), powers[i]);
2381 }
2382 }
2383
2384 /******************************************************************************/
2385 /* String and repr */
2386 /******************************************************************************/
2387
2388 static void
StringReprTest()2389 StringReprTest()
2390 {
2391 assertEqual(context, context_template);
2392
2393 context.traps(DecMaxStatus);
2394
2395 std::stringstream ss;
2396
2397 Decimal d = Decimal("225E+1000");
2398
2399 ss << d;
2400 assertEqual(ss.str(), "2.25E+1002");
2401
2402 assertEqual(d.repr(), "Decimal(\"2.25E+1002\")");
2403 assertEqual(d.repr(true), "Decimal(\"2.25E+1002\")");
2404 assertEqual(d.repr(false), "Decimal(\"2.25e+1002\")");
2405
2406 assertEqual(context.status(), 0U);
2407 }
2408
2409 /******************************************************************************/
2410 /* Format */
2411 /******************************************************************************/
2412
2413 static void
FormatTest()2414 FormatTest()
2415 {
2416 assertEqual(context, context_template);
2417
2418 const std::vector<std::vector<const char *>> test_cases = {
2419 {"e", "0E-15", "0e-15"},
2420 {"e", "2.3E-15", "2.3e-15"},
2421 {"e", "2.30E+2", "2.30e+2"},
2422 {"e", "2.30000E-15", "2.30000e-15"},
2423 {"e", "1.23456789123456789e40", "1.23456789123456789e+40"},
2424 {"e", "1.5", "1.5e+0"},
2425 {"e", "0.15", "1.5e-1"},
2426 {"e", "0.015", "1.5e-2"},
2427 {"e", "0.0000000000015", "1.5e-12"},
2428 {"e", "15.0", "1.50e+1"},
2429 {"e", "-15", "-1.5e+1"},
2430 {"e", "0", "0e+0"},
2431 {"e", "0E1", "0e+1"},
2432 {"e", "0.0", "0e-1"},
2433 {"e", "0.00", "0e-2"},
2434 {".6e", "0E-15", "0.000000e-9"},
2435 {".6e", "0", "0.000000e+6"},
2436 {".6e", "9.999999", "9.999999e+0"},
2437 {".6e", "9.9999999", "1.000000e+1"},
2438 {".6e", "-1.23e5", "-1.230000e+5"},
2439 {".6e", "1.23456789e-3", "1.234568e-3"},
2440 {"f", "0", "0"},
2441 {"f", "0.0", "0.0"},
2442 {"f", "0E-2", "0.00"},
2443 {"f", "0.00E-8", "0.0000000000"},
2444 {"f", "0E1", "0"},
2445 {"f", "3.2E1", "32"},
2446 {"f", "3.2E2", "320"},
2447 {"f", "3.20E2", "320"},
2448 {"f", "3.200E2", "320.0"},
2449 {"f", "3.2E-6", "0.0000032"},
2450 {".6f", "0E-15", "0.000000"},
2451 {".6f", "0E1", "0.000000"},
2452 {".6f", "0", "0.000000"},
2453 {".0f", "0", "0"},
2454 {".0f", "0e-2", "0"},
2455 {".0f", "3.14159265", "3"},
2456 {".1f", "3.14159265", "3.1"},
2457 {".4f", "3.14159265", "3.1416"},
2458 {".6f", "3.14159265", "3.141593"},
2459 {".7f", "3.14159265", "3.1415926"},
2460 {".8f", "3.14159265", "3.14159265"},
2461 {".9f", "3.14159265", "3.141592650"},
2462
2463 {"g", "0", "0"},
2464 {"g", "0.0", "0.0"},
2465 {"g", "0E1", "0e+1"},
2466 {"G", "0E1", "0E+1"},
2467 {"g", "0E-5", "0.00000"},
2468 {"g", "0E-6", "0.000000"},
2469 {"g", "0E-7", "0e-7"},
2470 {"g", "-0E2", "-0e+2"},
2471 {".0g", "3.14159265", "3"},
2472 {".0n", "3.14159265", "3"},
2473 {".1g", "3.14159265", "3"},
2474 {".2g", "3.14159265", "3.1"},
2475 {".5g", "3.14159265", "3.1416"},
2476 {".7g", "3.14159265", "3.141593"},
2477 {".8g", "3.14159265", "3.1415926"},
2478 {".9g", "3.14159265", "3.14159265"},
2479 {".10g", "3.14159265", "3.14159265"},
2480
2481 {"%", "0E1", "0%"},
2482 {"%", "0E0", "0%"},
2483 {"%", "0E-1", "0%"},
2484 {"%", "0E-2", "0%"},
2485 {"%", "0E-3", "0.0%"},
2486 {"%", "0E-4", "0.00%"},
2487
2488 {".3%", "0", "0.000%"},
2489 {".3%", "0E10", "0.000%"},
2490 {".3%", "0E-10", "0.000%"},
2491 {".3%", "2.34", "234.000%"},
2492 {".3%", "1.234567", "123.457%"},
2493 {".0%", "1.23", "123%"},
2494
2495 {"e", "NaN", "NaN"},
2496 {"f", "-NaN123", "-NaN123"},
2497 {"+g", "NaN456", "+NaN456"},
2498 {".3e", "Inf", "Infinity"},
2499 {".16f", "-Inf", "-Infinity"},
2500 {".0g", "-sNaN", "-sNaN"},
2501
2502 {"", "1.00", "1.00"},
2503
2504 {"6", "123", " 123"},
2505 {"<6", "123", "123 "},
2506 {">6", "123", " 123"},
2507 {"^6", "123", " 123 "},
2508 {"=+6", "123", "+ 123"},
2509 {"#<10", "NaN", "NaN#######"},
2510 {"#<10", "-4.3", "-4.3######"},
2511 {"#<+10", "0.0130", "+0.0130###"},
2512 {"#< 10", "0.0130", " 0.0130###"},
2513 {"@>10", "-Inf", "@-Infinity"},
2514 {"#>5", "-Inf", "-Infinity"},
2515 {"?^5", "123", "?123?"},
2516 {"%^6", "123", "%123%%"},
2517 {" ^6", "-45.6", "-45.6 "},
2518 {"/=10", "-45.6", "-/////45.6"},
2519 {"/=+10", "45.6", "+/////45.6"},
2520 {"/= 10", "45.6", " /////45.6"},
2521
2522 {",", "1234567", "1,234,567"},
2523 {",", "123456", "123,456"},
2524 {",", "12345", "12,345"},
2525 {",", "1234", "1,234"},
2526 {",", "123", "123"},
2527 {",", "12", "12"},
2528 {",", "1", "1"},
2529 {",", "0", "0"},
2530 {",", "-1234567", "-1,234,567"},
2531 {",", "-123456", "-123,456"},
2532 {"7,", "123456", "123,456"},
2533 {"8,", "123456", " 123,456"},
2534 {"08,", "123456", "0,123,456"},
2535 {"+08,", "123456", "+123,456"},
2536 {" 08,", "123456", " 123,456"},
2537 {"08,", "-123456", "-123,456"},
2538 {"+09,", "123456", "+0,123,456"},
2539
2540 {"07,", "1234.56", "1,234.56"},
2541 {"08,", "1234.56", "1,234.56"},
2542 {"09,", "1234.56", "01,234.56"},
2543 {"010,", "1234.56", "001,234.56"},
2544 {"011,", "1234.56", "0,001,234.56"},
2545 {"012,", "1234.56", "0,001,234.56"},
2546 {"08,.1f", "1234.5", "01,234.5"},
2547
2548 {",", "1.23456789", "1.23456789"},
2549 {",%", "123.456789", "12,345.6789%"},
2550 {",e", "123456", "1.23456e+5"},
2551 {",E", "123456", "1.23456E+5"},
2552
2553 {"a=-7.0", "0.12345", "aaaa0.1"},
2554
2555 {"<^+15.20%", "inf", "<<+Infinity%<<<"},
2556 {"\x07>,%", "sNaN1234567", "sNaN1234567%"},
2557 {"=10.10%", "NaN123", " NaN123%"},
2558 };
2559
2560 for (const std::vector<const char *>& v : test_cases) {
2561 const char *fmt = v.at(0);
2562 const char *d = v.at(1);
2563 const char *result = v.at(2);
2564 assertEqual(Decimal(d).format(fmt), result);
2565 assertEqual(Decimal(std::string(d)).format(std::string(fmt)), result);
2566 }
2567
2568 assertRaises(ValueError, [](){ Decimal(1).format("<>=10.10"); });
2569 const std::string fmt = "=" + std::to_string(MPD_SSIZE_MAX) + ".1";
2570 assertRaises(ValueError, [&](){ Decimal("1.23456789").format(fmt); });
2571 }
2572
2573 /******************************************************************************/
2574 /* Run tests */
2575 /******************************************************************************/
2576
2577 struct test_case {
2578 const char *name;
2579 void (*f)(void);
2580 };
2581
2582 static const size_t NUM_TESTS = 35;
2583 static const std::array<struct test_case, NUM_TESTS> test_cases {
2584 {
2585 /* Context tests */
2586 { "ExceptionHierarchyTest", ExceptionHierarchyTest },
2587 { "IEEEContextTest", IEEEContextTest },
2588 { "ContextGetSetTest", ContextGetSetTest },
2589 { "ContextInputValidationTest", ContextInputValidationTest },
2590 { "SmallContextTest", SmallContextTest },
2591 { "ContextReprTest", ContextReprTest },
2592
2593 /* Decimal tests */
2594 { "ExactConstructionTest", ExactConstructionTest },
2595 { "InexactConstructionTest", InexactConstructionTest },
2596 { "ConstructionExceptionTest", ConstructionExceptionTest },
2597
2598 { "AccessorTest", AccessorTest },
2599
2600 { "UnaryOperatorTest", UnaryOperatorTest },
2601 { "PointerUnaryOperatorTest", PointerUnaryOperatorTest },
2602
2603 { "ComparisonOperatorTest", ComparisonOperatorTest },
2604 { "PointerComparisonOperatorTest", PointerComparisonOperatorTest },
2605
2606 { "AssignmentOperatorTest", AssignmentOperatorTest },
2607 { "PointerAssignmentOperatorTest", PointerAssignmentOperatorTest },
2608
2609 { "ArithmeticOperatorTest", ArithmeticOperatorTest },
2610 { "PointerArithmeticOperatorTest", PointerArithmeticOperatorTest },
2611
2612 { "PredicateTest", PredicateTest },
2613 { "UnaryFunctionTest", UnaryFunctionTest },
2614
2615 { "CeilTest", CeilTest },
2616 { "FloorTest", FloorTest },
2617 { "TruncTest", TruncTest },
2618
2619 { "BinaryFunctionTest", BinaryFunctionTest },
2620 { "DivmodTest", DivmodTest },
2621 { "QuantizeTest", QuantizeTest },
2622
2623 { "TernaryFunctionTest", TernaryFunctionTest },
2624
2625 { "IrregularFunctionTest", IrregularFunctionTest },
2626 { "ApplyTest", ApplyTest },
2627
2628 { "IntegerConversionTest", IntegerConversionTest },
2629
2630 { "ExactArithTest", ExactArithTest },
2631
2632 { "DataStructuresTest", DataStructuresTest },
2633 { "LargeDataStructuresTest", LargeDataStructuresTest },
2634
2635 { "StringReprTest", StringReprTest },
2636 { "FormatTest", FormatTest },
2637 }
2638 };
2639
2640 static int
exit_status(const std::vector<std::string> & status)2641 exit_status(const std::vector<std::string>& status)
2642 {
2643 for (auto p : status) {
2644 if (p != "PASS") {
2645 return EXIT_FAILURE;
2646 }
2647 }
2648
2649 return EXIT_SUCCESS;
2650 }
2651
2652 /* run a single function */
2653 static void
do_test(const struct test_case & t,std::vector<std::string> & status,size_t i)2654 do_test(const struct test_case& t, std::vector<std::string>& status, size_t i)
2655 {
2656 try {
2657 assertEqual(context, context_template);
2658
2659 t.f();
2660 } catch (Failure& e) {
2661 status[i] = e.what();
2662 }
2663 }
2664
2665 /* process a function list */
2666 static int
do_tests(const std::array<struct test_case,NUM_TESTS> & tests)2667 do_tests(const std::array<struct test_case, NUM_TESTS>& tests)
2668 {
2669 const size_t n = tests.size();
2670 std::vector<std::string> status(n, "PASS");
2671
2672 for (size_t i = 0; i < n; i++) {
2673 std::cout << tests[i].name << " ... " << std::flush;
2674 do_test(tests[i], status, i);
2675 context = context_template;
2676 std::cout << status[i] << "\n" << std::flush;
2677 }
2678
2679 std::cout << "\n" << std::flush;
2680
2681 return exit_status(status);
2682 }
2683
2684 /* process a file list, threaded */
2685 static int
do_tests_threaded(const std::array<struct test_case,NUM_TESTS> & tests)2686 do_tests_threaded(const std::array<struct test_case, NUM_TESTS>& tests)
2687 {
2688 const size_t n = tests.size();
2689 std::vector<std::string> status(n, "PASS");
2690 std::vector<std::thread> t(n);
2691
2692 for (size_t i = 0; i < n; i++) {
2693 t[i] = std::thread(do_test, tests[i], std::ref(status), i);
2694 }
2695
2696 for (size_t i = 0; i < n; i++) {
2697 t[i].join();
2698 }
2699
2700 for (size_t i = 0; i < n; i++) {
2701 std::cout << tests[i].name << " ... " << status[i] << "\n" << std::flush;
2702 }
2703
2704 std::cout << "\n" << std::flush;
2705
2706 return exit_status(status);
2707 }
2708
2709 /* repeatedly process a randomized function list */
2710 static int
do_tests_repeat(const std::array<struct test_case,NUM_TESTS> & tests)2711 do_tests_repeat(const std::array<struct test_case, NUM_TESTS>& tests)
2712 {
2713 const size_t n = tests.size();
2714 std::vector<std::string> status(n, "PASS");
2715 std::random_device rd;
2716 std::mt19937 g(rd());
2717 std::vector<size_t> a(n);
2718
2719 for (size_t i = 0; i < n; i++) {
2720 a[i] = i;
2721 }
2722
2723 for (int64_t i = 0; i < 100; i++) {
2724 std::shuffle(a.begin(), a.end(), g);
2725
2726 for (size_t k = 0; k < n; k++) {
2727 do_test(tests[a[k]], status, a[k]);
2728 context = context_template;
2729 }
2730
2731 if (exit_status(status) != EXIT_SUCCESS) {
2732 exit(EXIT_FAILURE);
2733 }
2734 }
2735
2736 return EXIT_SUCCESS;
2737 }
2738
2739 /* process a file list, threaded */
2740 static int
do_tests_threaded_repeat(const std::array<struct test_case,NUM_TESTS> & tests)2741 do_tests_threaded_repeat(const std::array<struct test_case, NUM_TESTS>& tests)
2742 {
2743 const size_t n = tests.size();
2744 std::vector<std::string> status(n, "PASS");
2745 std::vector<std::thread> t(n);
2746 std::random_device rd;
2747 std::mt19937 g(rd());
2748 std::vector<size_t> a(n);
2749
2750 for (size_t i = 0; i < n; i++) {
2751 a[i] = i;
2752 }
2753
2754 for (int64_t i = 0; i < 100; i++) {
2755 std::shuffle(a.begin(), a.end(), g);
2756
2757 for (size_t k = 0; k < n; k++) {
2758 t[k] = std::thread(do_test, tests[a[k]], std::ref(status), a[k]);
2759 }
2760
2761 for (size_t k = 0; k < n; k++) {
2762 t[k].join();
2763 }
2764
2765 if (exit_status(status) != EXIT_SUCCESS) {
2766 exit(EXIT_FAILURE);
2767 }
2768 }
2769
2770 return EXIT_SUCCESS;
2771 }
2772
2773
2774 /*
2775 * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77704
2776 *
2777 * valgrind --tool=helgrind shows a data race in libstdc++. The race
2778 * disappears when streams are used before calling any threads.
2779 */
2780 static void
init_libc(void)2781 init_libc(void)
2782 {
2783 std::ostringstream ss;
2784 ss << 1;
2785 }
2786
2787 static void
usage(void)2788 usage(void)
2789 {
2790 std::cerr << "apitest: usage: apitest [--custom] [--thread] [--repeat]" << std::endl;
2791 exit(EXIT_FAILURE);
2792 }
2793
2794 int
main(int argc,char * argv[])2795 main(int argc, char *argv[])
2796 {
2797 std::vector<std::string> args(argv + (argc!=0), argv + argc);
2798 bool custom_alloc = false;
2799 bool thread = false;
2800 bool repeat = false;
2801
2802 for (auto arg : args) {
2803 if (!custom_alloc && arg == "--custom") {
2804 custom_alloc = true;
2805 }
2806 else if (!thread && arg == "--thread") {
2807 thread = true;
2808 }
2809 else if (!repeat && arg == "--repeat") {
2810 repeat = true;
2811 }
2812 else {
2813 usage();
2814 }
2815 }
2816
2817 /* Initialize streams (see above) */
2818 init_libc();
2819
2820 /* Initialize custom allocation functions */
2821 test::init_alloc(custom_alloc, /*check_alloc=*/false);
2822
2823 /* Initialize context template */
2824 context_template = Context(9, 999999, -999999, ROUND_HALF_EVEN, 0, 0, 0);
2825
2826 /* Initialize context for the main thread */
2827 context = context_template;
2828
2829 /* Check version numbers */
2830 static_assert(MPD_MAJOR_VERSION == 4, "MPD_MAJOR_VERSION must be 4");
2831 static_assert(MPD_MINOR_VERSION == 0, "MPD_MINOR_VERSION must be 0");
2832 static_assert(MPD_MICRO_VERSION == 0, "MPD_MICRO_VERSION must be 0");
2833
2834 if (mpd_version() != std::string("4.0.0")) {
2835 err_exit("mpd_version() != 4.0.0");
2836 }
2837 if (MPD_VERSION != std::string("4.0.0")) {
2838 err_exit("MPD_VERSION != 4.0.0");
2839 }
2840
2841 /* Check fundamental libmpdec++ invariant */
2842 assertEqual(MPD_MINALLOC, decimal::MINALLOC);
2843
2844
2845 if (thread) {
2846 if (repeat) {
2847 return do_tests_threaded_repeat(test_cases);
2848 }
2849 else {
2850 return do_tests_threaded(test_cases);
2851 }
2852 }
2853 else {
2854 if (repeat) {
2855 return do_tests_repeat(test_cases);
2856 }
2857 else {
2858 return do_tests(test_cases);
2859 }
2860 }
2861 }
2862