• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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