• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2008-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 #if defined(__GNUC__) || defined(__COMPCERT__)
29   #define _GNU_SOURCE
30 #endif
31 
32 
33 #include <assert.h>
34 #include <ctype.h>
35 #include <errno.h>
36 #include <limits.h>
37 #include <locale.h>
38 #include <stdint.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <time.h>
43 
44 #include "mpdecimal.h"
45 #include "test.h"
46 #include "vctest.h"
47 
48 
49 #define MAXLINE 400000
50 #define MAXTOKEN 32
51 
52 #ifndef _MSC_VER
53   #include <inttypes.h>
54   #define ASSERT(p) if (!(p)) {abort();}
55 #else
56   #define ASSERT(p) if (!(p)) {mpd_err_fatal("assertion failed");}
57 #endif
58 
59 
60 static int extended = 1;
61 static int global_failure = 0;
62 static int file_failure = 0;
63 
64 static mpd_ssize_t
strtossize(const char * s,char ** end,int base)65 strtossize(const char *s, char **end, int base)
66 {
67     int64_t retval;
68 
69     errno = 0;
70     retval = _mpd_strtossize(s, end, base);
71     if (errno == 0 && (retval > MPD_SSIZE_MAX || retval < MPD_SSIZE_MIN)) {
72         errno = ERANGE;
73     }
74     if (errno == ERANGE) {
75         return (retval < 0) ? MPD_SSIZE_MIN : MPD_SSIZE_MAX;
76     }
77 
78     return (mpd_ssize_t)retval;
79 }
80 
81 static void
mpd_init_rand(mpd_t * x)82 mpd_init_rand(mpd_t *x)
83 {
84     long r = random() % 100;
85     uint8_t sign = random()%2;
86 
87     if (r >= 80) {
88         mpd_minalloc(x);
89     }
90     else if (r >= 60) {
91         mpd_minalloc(x);
92         mpd_set_flags(x, sign);
93     }
94     else if (r >= 40) {
95         mpd_setspecial(x, sign, MPD_NAN);
96     }
97     else if (r >= 20) {
98         mpd_setspecial(x, sign, MPD_SNAN);
99     }
100     else {
101         mpd_setspecial(x, sign, MPD_INF);
102     }
103 }
104 
105 /* These ranges are needed for the official test suite
106  * and are generally not problematic at all. */
107 #if defined(MPD_CONFIG_64)
108   #define MPD_READ_MAX_PREC 1070000000000000000LL
109 #elif defined(MPD_CONFIG_32)
110   #define MPD_READ_MAX_PREC 1070000000
111 #else
112   #error "config not defined"
113 #endif
114 
115 static void
mpd_readcontext(mpd_context_t * ctx)116 mpd_readcontext(mpd_context_t *ctx)
117 {
118     if (extended) {
119         ctx->prec=MPD_READ_MAX_PREC;
120         ctx->emax=MPD_READ_MAX_PREC;
121         ctx->emin=-MPD_READ_MAX_PREC;
122     }
123     else {
124         ctx->prec=MPD_MAX_PREC;
125         ctx->emax=MPD_MAX_EMAX;
126         ctx->emin=MPD_MIN_EMIN;
127     }
128 
129     ctx->round=MPD_ROUND_HALF_UP;
130     ctx->traps=MPD_Traps;
131     ctx->status=0;
132     ctx->newtrap=0;
133     ctx->clamp=0;
134     ctx->allcr=1;
135 }
136 
137 static void
mpd_testcontext(mpd_context_t * ctx)138 mpd_testcontext(mpd_context_t *ctx)
139 {
140     if (extended) {
141     #if defined(MPD_CONFIG_64)
142         ctx->prec=MPD_MAX_PREC;
143         ctx->emax=MPD_MAX_EMAX;
144         ctx->emin=MPD_MIN_EMIN;
145     #elif defined(MPD_CONFIG_32)
146         /* These ranges are needed for the official test suite. */
147         ctx->prec=999999999;
148         ctx->emax=999999999;
149         ctx->emin=-999999999;
150     #else
151       #error "config not defined"
152     #endif
153     }
154     else {
155         ctx->prec=MPD_MAX_PREC;
156         ctx->emax=MPD_MAX_EMAX;
157         ctx->emin=MPD_MIN_EMIN;
158     }
159 
160     ctx->round=MPD_ROUND_HALF_UP;
161     ctx->traps=MPD_Traps;
162     ctx->status=0;
163     ctx->newtrap=0;
164     ctx->clamp=0;
165     ctx->allcr=1;
166 }
167 
168 static void
mpd_assert_context_ok(const mpd_context_t * ctx)169 mpd_assert_context_ok(const mpd_context_t *ctx)
170 {
171     ASSERT(0 < ctx->prec && ctx->prec <= MPD_READ_MAX_PREC);
172     ASSERT(0 <= ctx->emax && ctx->emax <= MPD_READ_MAX_PREC);
173     ASSERT(-MPD_READ_MAX_PREC <= ctx->emin && ctx->emin <= 0);
174     ASSERT(0 <= ctx->round && ctx->round < MPD_ROUND_GUARD);
175     ASSERT(ctx->traps <= MPD_Max_status);
176     ASSERT(ctx->status <= MPD_Max_status);
177     ASSERT(ctx->clamp == 0 || ctx->clamp == 1);
178     ASSERT(ctx->allcr == 0 || ctx->allcr == 1);
179 }
180 
181 /* Known differences that are within the spec. */
182 struct result_diff {
183     const char *id;
184     const char *calc;
185     const char *expected;
186 };
187 
188 struct status_diff {
189     const char *id;
190     uint32_t calc;
191     uint32_t expected;
192 };
193 
194 static struct result_diff ulp_cases[] = {
195     /* Cases where the result is allowed to differ by less than one ULP.
196      * Only needed if ctx->allcr is 0. */
197     { "expx013", "1.001000", "1.001001" },
198     { "expx020", "1.000000", "1.000001" },
199     { "expx109", "0.999999910000004049999878", "0.999999910000004049999879" },
200     { "expx1036", "1.005088", "1.005087" },
201     { "expx350", "1.0000000", "1.0000001" },
202     { "expx351", "1.0000000", "1.0000001" },
203     { "expx352", "1.0000000", "1.0000001" },
204     {NULL, NULL, NULL}
205 };
206 
207 static struct status_diff status_cases[] = {
208     /* With a reduced working precision in mpd_qpow() the status matches. */
209     { "pwsx803", MPD_Inexact|MPD_Rounded|MPD_Subnormal|MPD_Underflow, MPD_Inexact|MPD_Rounded },
210     {NULL, 0, 0}
211 };
212 
213 static const char *skipit[] = {
214     /* NULL reference, decimal16, decimal32, or decimal128 */
215     "absx900",
216     "addx9990",
217     "addx9991",
218     "clam090",
219     "clam091",
220     "clam092",
221     "clam093",
222     "clam094",
223     "clam095",
224     "clam096",
225     "clam097",
226     "clam098",
227     "clam099",
228     "clam189",
229     "clam190",
230     "clam191",
231     "clam192",
232     "clam193",
233     "clam194",
234     "clam195",
235     "clam196",
236     "clam197",
237     "clam198",
238     "clam199",
239     "comx990",
240     "comx991",
241     "cotx9990",
242     "cotx9991",
243     "ctmx9990",
244     "ctmx9991",
245     "ddabs900",
246     "ddadd9990",
247     "ddadd9991",
248     "ddcom9990",
249     "ddcom9991",
250     "ddcot9990",
251     "ddcot9991",
252     "ddctm9990",
253     "ddctm9991",
254     "dddiv9998",
255     "dddiv9999",
256     "dddvi900",
257     "dddvi901",
258     "ddfma2990",
259     "ddfma2991",
260     "ddfma39990",
261     "ddfma39991",
262     "ddlogb900",
263     "ddmax900",
264     "ddmax901",
265     "ddmxg900",
266     "ddmxg901",
267     "ddmin900",
268     "ddmin901",
269     "ddmng900",
270     "ddmng901",
271     "ddmul9990",
272     "ddmul9991",
273     "ddnextm900",
274     "ddnextm900",
275     "ddnextp900",
276     "ddnextp900",
277     "ddnextt900",
278     "ddnextt901",
279     "ddqua998",
280     "ddqua999",
281     "ddred900",
282     "ddrem1000",
283     "ddrem1001",
284     "ddrmn1000",
285     "ddrmn1001",
286     "ddsub9990",
287     "ddsub9991",
288     "ddintx074",
289     "ddintx094",
290     "divx9998",
291     "divx9999",
292     "dvix900",
293     "dvix901",
294     "dqabs900",
295     "dqadd9990",
296     "dqadd9991",
297     "dqcom990",
298     "dqcom991",
299     "dqcot9990",
300     "dqcot9991",
301     "dqctm9990",
302     "dqctm9991",
303     "dqdiv9998",
304     "dqdiv9999",
305     "dqdvi900",
306     "dqdvi901",
307     "dqfma2990",
308     "dqfma2991",
309     "dqadd39990",
310     "dqadd39991",
311     "dqlogb900",
312     "dqmax900",
313     "dqmax901",
314     "dqmxg900",
315     "dqmxg901",
316     "dqmin900",
317     "dqmin901",
318     "dqmng900",
319     "dqmng901",
320     "dqmul9990",
321     "dqmul9991",
322     "dqnextm900",
323     "dqnextp900",
324     "dqnextt900",
325     "dqnextt901",
326     "dqqua998",
327     "dqqua999",
328     "dqred900",
329     "dqrem1000",
330     "dqrem1001",
331     "dqrmn1000",
332     "dqrmn1001",
333     "dqsub9990",
334     "dqsub9991",
335     "dqintx074",
336     "dqintx094",
337     "expx900",
338     "fmax2990",
339     "fmax2991",
340     "fmax39990",
341     "fmax39991",
342     "lnx900",
343     "logx900",
344     "logbx900",
345     "maxx900",
346     "maxx901",
347     "mxgx900",
348     "mxgx901",
349     "mnm900",
350     "mnm901",
351     "mng900",
352     "mng901",
353     "minx900",
354     "mulx990",
355     "mulx991",
356     "nextm900",
357     "nextp900",
358     "nextt900",
359     "nextt901",
360     "plu900",
361     "powx900",
362     "powx901",
363     "pwsx900",
364     "quax1022",
365     "quax1023",
366     "quax1024",
367     "quax1025",
368     "quax1026",
369     "quax1027",
370     "quax1028",
371     "quax1029",
372     "quax0a2",
373     "quax0a3",
374     "quax998",
375     "quax999",
376     "redx900",
377     "remx1000",
378     "remx1001",
379     "rmnx900",
380     "rmnx901",
381     "sqtx9900",
382     "subx9990",
383     "subx9991",
384     /* operand range violations, invalid context */
385     "expx901",
386     "expx902",
387     "expx903",
388     "expx905",
389     "lnx901",
390     "lnx902",
391     "lnx903",
392     "lnx905",
393     "logx901",
394     "logx902",
395     "logx903",
396     "logx905",
397     "powx1183",
398     "powx1184",
399     "powx4001",
400     "powx4002",
401     "powx4003",
402     "powx4005",
403     "powx4008",
404     "powx4010",
405     "powx4012",
406     "powx4014",
407     "scbx164",
408     "scbx165",
409     "scbx166",
410 #if defined(MPD_CONFIG_32) && MPD_MINALLOC_MAX <= 4
411     /* Under the allocation failure tests, the result is numerically correct
412        (1 == 1.00000) but without zero padding. This is by design, since in
413        case of MPD_Malloc_error mpd_qsqrt() retries the operation with a lower
414        context precision and allows all exact results.
415 
416        The MPD_MINALLOC_MAX < 64 feature is is officially unsupported but works
417        (if the little-endian mpd_ln10_data arrays are adjusted).
418     */
419     "sqtx9045",
420 #endif
421     /* skipped for decNumber, too */
422     "powx4302",
423     "powx4303",
424     "powx4303",
425     "powx4342",
426     "powx4343",
427     "pwsx805",
428     /* disagreement for three arg power */
429     "pwmx325",
430     "pwmx326",
431     NULL
432 };
433 
434 static inline int
startswith(const char * token,const char * s)435 startswith(const char *token, const char *s)
436 {
437     return token != NULL && strncasecmp(token, s, strlen(s)) == 0;
438 }
439 
440 static inline int
eqtoken(const char * token,const char * s)441 eqtoken(const char *token, const char *s)
442 {
443     return token != NULL && strcasecmp(token, s) == 0;
444 }
445 
446 static int
check_skip(char * id)447 check_skip(char *id)
448 {
449     int i;
450 
451     for (i = 0; skipit[i] != NULL; i++) {
452         if (eqtoken(id, skipit[i])) {
453 #if defined(RT_VERBOSITY) && RT_VERBOSITY == 2
454             fprintf(stderr, "SKIP: %s\n", id);
455 #endif
456             return 1;
457         }
458     }
459 
460     return 0;
461 }
462 
463 static char *
nexttoken(char * cp)464 nexttoken(char *cp)
465 {
466     static char *start = NULL;
467     static char *end = NULL;
468 
469     if (cp == NULL) {
470         assert(end != NULL);
471         cp = end;
472     }
473 
474     for (; *cp != '\0'; cp++) {
475         if (isspace((unsigned char)*cp)) {
476             /* empty */
477         }
478         else if (*cp == '"') {
479             start = end = cp+1;
480             for (; *end != '\0'; end++) {
481                 if (*end == '"' && *(end+1) == '"')
482                     end += 1;
483                 else if (*end == '"')
484                     break;
485             }
486             if (*end == '\0')
487                 return NULL;
488             *end++ = '\0';
489             return start;
490         }
491         else if (*cp == '\'') {
492             start = end = cp+1;
493             for (; *end != '\0'; end++) {
494                 if (*end == '\'' && *(end+1) == '\'')
495                     end += 1;
496                 else if (*end == '\'')
497                     break;
498             }
499             if (*end == '\0')
500                 return NULL;
501             *end++ = '\0';
502             return start;
503         }
504         else {
505             start = end = cp;
506             for (; *end != '\0'; end++)
507                 if (isspace((unsigned char)*end))
508                     break;
509             if (*end == '\0')
510                 return NULL;
511             *end++ = '\0';
512             return start;
513         }
514     }
515 
516     return NULL;
517 }
518 
519 /* split a line into tokens */
520 static int
split(char * token[],char line[])521 split(char *token[], char line[])
522 {
523     char *cp;
524     size_t len;
525     int n = 0;
526 
527     cp = nexttoken(line);
528     while (n < MAXTOKEN && cp != NULL) {
529         len = strlen(cp);
530         if ((token[n] = malloc(len+1)) == NULL) {
531             mpd_err_fatal("out of memory");
532         }
533         strcpy(token[n], cp);
534         cp = nexttoken(NULL);
535         n++;
536     }
537     token[n] = NULL;
538 
539     return n;
540 }
541 
542 static void
freetoken(char ** token)543 freetoken(char **token)
544 {
545     while (*token != NULL) {
546         free(*token++);
547     }
548 }
549 
550 /* returns all expected conditions in a status flag */
551 static uint32_t
scan_conditions(char ** token)552 scan_conditions(char **token)
553 {
554     char *condition = *token;
555     uint32_t status = 0;
556 
557     while (condition != NULL) {
558 
559         if (startswith(condition, "--"))
560             break;
561         else if (eqtoken(condition, "Clamped"))
562             status |= MPD_Clamped;
563         else if (eqtoken(condition, "Conversion_syntax"))
564             status |= MPD_Conversion_syntax;
565         else if (eqtoken(condition, "Division_by_zero"))
566             status |= MPD_Division_by_zero;
567         else if (eqtoken(condition, "Division_impossible"))
568             status |= MPD_Division_impossible;
569         else if (eqtoken(condition, "Division_undefined"))
570             status |= MPD_Division_undefined;
571         else if (eqtoken(condition, "Fpu_error"))
572             status |= MPD_Fpu_error;
573         else if (eqtoken(condition, "Inexact"))
574             status |= MPD_Inexact;
575         else if (eqtoken(condition, "Invalid_context"))
576             status |= MPD_Invalid_context;
577         else if (eqtoken(condition, "Invalid_operation"))
578             status |= MPD_Invalid_operation;
579         else if (eqtoken(condition, "Malloc_error"))
580             status |= MPD_Malloc_error;
581         else if (eqtoken(condition, "Not_implemented"))
582             status |= MPD_Not_implemented;
583         else if (eqtoken(condition, "Overflow"))
584             status |= MPD_Overflow;
585         else if (eqtoken(condition, "Rounded"))
586             status |= MPD_Rounded;
587         else if (eqtoken(condition, "Subnormal"))
588             status |= MPD_Subnormal;
589         else if (eqtoken(condition, "Underflow"))
590             status |= MPD_Underflow;
591         else
592             mpd_err_fatal("unknown status: %s", condition);
593 
594         condition = *(++token);
595     }
596 
597     return status;
598 }
599 
600 static void
compare_expected(const char * calc,const char * expected,uint32_t expected_status,char * id,mpd_context_t * ctx)601 compare_expected(const char *calc, const char *expected, uint32_t expected_status,
602                  char *id, mpd_context_t *ctx)
603 {
604     char ctxstatus[MPD_MAX_FLAG_STRING];
605     char expstatus[MPD_MAX_FLAG_STRING];
606 
607 
608 #ifndef RT_VERBOSITY
609     /* Do not print known pseudo-failures. */
610     int i;
611 
612     /* known ULP diffs */
613     if (ctx->allcr == 0) {
614         for (i = 0; ulp_cases[i].id != NULL; i++) {
615             if (eqtoken(id, ulp_cases[i].id) &&
616                 strcmp(expected, ulp_cases[i].expected) == 0 &&
617                 strcmp(calc, ulp_cases[i].calc) == 0) {
618                 return;
619             }
620         }
621     }
622 
623     /* known status diffs */
624     for (i = 0; status_cases[i].id != NULL; i++) {
625         if (eqtoken(id, status_cases[i].id) &&
626             expected_status == status_cases[i].expected &&
627             ctx->status == status_cases[i].calc) {
628             return;
629         }
630     }
631 #endif
632 
633     if (strcmp(calc, expected) != 0) {
634         if (file_failure == 0) {
635             fputs("\n\n", stderr);
636         }
637         fprintf(stderr, "FAIL: %s  calc: %s  expected: %s\n",
638                         id, calc, expected);
639         global_failure = file_failure = 1;
640     }
641     if (ctx->status != expected_status) {
642         if (file_failure == 0) {
643             fputs("\n\n", stderr);
644         }
645         mpd_snprint_flags(ctxstatus, MPD_MAX_FLAG_STRING, ctx->status);
646         mpd_snprint_flags(expstatus, MPD_MAX_FLAG_STRING, expected_status);
647         fprintf(stderr, "FAIL: %s: status:  calc: %s  expected: %s\n",
648                 id, ctxstatus, expstatus);
649         global_failure = file_failure = 1;
650     }
651 }
652 
653 static int
equalmem(const mpd_t * a,const mpd_t * b)654 equalmem(const mpd_t *a, const mpd_t *b)
655 {
656     mpd_ssize_t i;
657 
658     if (a->flags != b->flags) return 0;
659     if (a->exp != b->exp) return 0;
660     if (a->len != b->len) return 0;
661     if (a->digits != b->digits) return 0;
662     for (i = 0; i < a->len; i++)
663         if (a->data[i] != b->data[i])
664             return 0;
665     return 1;
666 }
667 
668 static void
check_equalmem(const mpd_t * a,const mpd_t * b,const char * id)669 check_equalmem(const mpd_t *a, const mpd_t *b, const char *id)
670 {
671     if (!equalmem(a, b)) {
672         fprintf(stderr, "FAIL: const arg changed: %s\n", id);
673     }
674 }
675 
676 static unsigned long
get_testno(char * token)677 get_testno(char *token)
678 {
679     char *number;
680 
681     number = strpbrk(token, "0123456789");
682     ASSERT(number != NULL);
683     return strtoul(number, NULL, 10);
684 }
685 
686 /* scan a single operand and the expected result */
687 static int
scan_1op_result(mpd_t * op1,char ** result,char * token[],mpd_context_t * ctx)688 scan_1op_result(mpd_t *op1, char **result, char *token[], mpd_context_t *ctx)
689 {
690     /* operand 1 */
691     if (token[2] == NULL) {
692         mpd_err_fatal("parse error at id %s", token[0]);
693     }
694     mpd_set_string(op1, token[2], ctx);
695 
696     /* discard "->" */
697     if (token[3] == NULL) {
698         mpd_err_fatal("parse error at id %s", token[0]);
699     }
700 
701     /* expected result */
702     if (token[4] == NULL) {
703         mpd_err_fatal("parse error at id %s", token[0]);
704     }
705     *result = token[4];
706 
707     return 5;
708 }
709 
710 /* scan a single operand and two results */
711 static int
scan_1op_2results(mpd_t * op1,char ** result1,char ** result2,char * token[],mpd_context_t * ctx)712 scan_1op_2results(mpd_t *op1, char **result1, char **result2, char *token[], mpd_context_t *ctx)
713 {
714     /* operand 1 */
715     if (token[2] == NULL) {
716         mpd_err_fatal("parse error at id %s", token[0]);
717     }
718     mpd_set_string(op1, token[2], ctx);
719 
720     /* discard "->" */
721     if (token[3] == NULL) {
722         mpd_err_fatal("parse error at id %s", token[0]);
723     }
724 
725     /* expected result1 */
726     if (token[4] == NULL) {
727         mpd_err_fatal("parse error at id %s", token[0]);
728     }
729     *result1 = token[4];
730 
731     /* expected result2 */
732     if (token[5] == NULL) {
733         mpd_err_fatal("parse error at id %s", token[0]);
734     }
735     *result2 = token[5];
736 
737     return 6;
738 }
739 
740 /* scan decimal operand, string operand and the expected result */
741 static int
scan_1op_str_result(mpd_t * op1,char ** op2,char ** result,char * token[],mpd_context_t * ctx)742 scan_1op_str_result(mpd_t *op1, char **op2, char **result, char *token[], mpd_context_t *ctx)
743 {
744     /* operand 1 */
745     if (token[2] == NULL) {
746         mpd_err_fatal("%s", token[0]);
747     }
748     mpd_set_string(op1, token[2], ctx);
749 
750     /* operand 2 */
751     if (token[3] == NULL) {
752         mpd_err_fatal("%s", token[0]);
753     }
754     *op2 = token[3];
755 
756     /* discard "->" */
757     if (token[4] == NULL) {
758         mpd_err_fatal("%s", token[0]);
759     }
760 
761     /* expected result */
762     if (token[5] == NULL) {
763         mpd_err_fatal("%s", token[0]);
764     }
765     *result = token[5];
766 
767     return 6;
768 }
769 
770 /* scan two operands and the expected result */
771 static int
scan_2ops_result(mpd_t * op1,mpd_t * op2,char ** result,char * token[],mpd_context_t * ctx)772 scan_2ops_result(mpd_t *op1, mpd_t *op2, char **result, char *token[], mpd_context_t *ctx)
773 {
774     /* operand 1 */
775     if (token[2] == NULL) {
776         mpd_err_fatal("%s", token[0]);
777     }
778     mpd_set_string(op1, token[2], ctx);
779 
780     /* operand 2 */
781     if (token[3] == NULL) {
782         mpd_err_fatal("%s", token[0]);
783     }
784     mpd_set_string(op2, token[3], ctx);
785 
786     /* discard "->" */
787     if (token[4] == NULL) {
788         mpd_err_fatal("%s", token[0]);
789     }
790 
791     /* expected result */
792     if (token[5] == NULL) {
793         mpd_err_fatal("%s", token[0]);
794     }
795     *result = token[5];
796 
797     return 6;
798 }
799 
800 /* scan two operands and two results */
801 static int
scan_2ops_2results(mpd_t * op1,mpd_t * op2,char ** result1,char ** result2,char * token[],mpd_context_t * ctx)802 scan_2ops_2results(mpd_t *op1, mpd_t *op2, char **result1, char **result2, char *token[], mpd_context_t *ctx)
803 {
804     /* operand 1 */
805     if (token[2] == NULL) {
806         mpd_err_fatal("%s", token[0]);
807     }
808     mpd_set_string(op1, token[2], ctx);
809 
810     /* operand 2 */
811     if (token[3] == NULL) {
812         mpd_err_fatal("%s", token[0]);
813     }
814     mpd_set_string(op2, token[3], ctx);
815 
816     /* discard "->" */
817     if (token[4] == NULL) {
818         mpd_err_fatal("%s", token[0]);
819     }
820 
821     /* expected result1 */
822     if (token[5] == NULL) {
823         mpd_err_fatal("%s", token[0]);
824     }
825     *result1 = token[5];
826 
827     /* expected result2 */
828     if (token[6] == NULL) {
829         mpd_err_fatal("%s", token[0]);
830     }
831     *result2 = token[6];
832 
833     return 7;
834 }
835 
836 /* scan three operands and the expected result */
837 static int
scan_3ops_result(mpd_t * op1,mpd_t * op2,mpd_t * op3,char ** result,char * token[],mpd_context_t * ctx)838 scan_3ops_result(mpd_t *op1, mpd_t *op2, mpd_t *op3, char **result, char *token[], mpd_context_t *ctx)
839 {
840     /* operand 1 */
841     if (token[2] == NULL) {
842         mpd_err_fatal("%s", token[0]);
843     }
844     mpd_set_string(op1, token[2], ctx);
845 
846     /* operand 2 */
847     if (token[3] == NULL) {
848         mpd_err_fatal("%s", token[0]);
849     }
850     mpd_set_string(op2, token[3], ctx);
851 
852     /* operand 2 */
853     if (token[4] == NULL) {
854         mpd_err_fatal("%s", token[0]);
855     }
856     mpd_set_string(op3, token[4], ctx);
857 
858     /* discard "->" */
859     if (token[5] == NULL) {
860         mpd_err_fatal("%s", token[0]);
861     }
862 
863     /* expected result */
864     if (token[6] == NULL) {
865         mpd_err_fatal("%s", token[0]);
866     }
867     *result = token[6];
868 
869     return 7;
870 }
871 
872 static mpd_t *op, *op1, *op2, *op3;
873 static mpd_t *tmp, *tmp1, *tmp2, *tmp3;
874 static mpd_t *result, *result1, *result2;
875 
876 /* Test triple conversion */
877 static void
_TripleTest(const mpd_t * a,mpd_context_t * ctx,const char * testno)878 _TripleTest(const mpd_t *a, mpd_context_t *ctx, const char *testno)
879 {
880     mpd_uint128_triple_t triple;
881     uint32_t status = 0;
882     int ret = 0;
883 
884 #ifdef MPD_CONFIG_32
885     /*
886      * 32-bit: as_triple() expects well-formed decimals. Skip test cases
887      * that use the extended exponent, which is safe in the tests but not
888      * in production.
889      */
890      if (a->exp < MPD_MIN_ETINY || a->exp > MPD_MAX_EMAX) {
891          return;
892      }
893 #endif
894 
895     triple = mpd_as_uint128_triple(a);
896     switch (triple.tag) {
897     case MPD_TRIPLE_QNAN: case MPD_TRIPLE_SNAN:
898         ASSERT(triple.exp == 0)
899         break;
900     case MPD_TRIPLE_INF:
901         ASSERT(triple.hi == 0 && triple.lo == 0 && triple.exp == 0)
902         break;
903     case MPD_TRIPLE_NORMAL:
904         break;
905     case MPD_TRIPLE_ERROR:
906         ASSERT(triple.sign == 0 && triple.hi == 0 && triple.lo == 0 && triple.exp == 0)
907         break;
908     }
909 
910     /* Allocation failures in from_triple() */
911     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
912         mpd_init_rand(result);
913 
914         mpd_set_alloc_fail(ctx);
915         status = 0;
916         ret = mpd_from_uint128_triple(result, &triple, &status);
917         mpd_set_alloc(ctx);
918 
919         if (!(status&MPD_Malloc_error)) {
920             break;
921         }
922         ASSERT(ret == -1)
923         ASSERT(mpd_isnan(result))
924     }
925 
926     if (triple.tag != MPD_TRIPLE_ERROR) {
927         ASSERT(ret == 0)
928         ASSERT(status == 0)
929         check_equalmem(result, a, testno);
930     }
931     else {
932         ASSERT(ret == -1)
933         ASSERT(status == MPD_Conversion_syntax)
934         ASSERT(mpd_isnan(result))
935     }
936 }
937 
938 /* Test both versions of mpd_to_sci. Do not use this if alloc_fail is set,
939    since MPD_Malloc_error will only be triggered for one of the functions. */
940 static char *
_mpd_to_sci(const mpd_t * dec,int fmt)941 _mpd_to_sci(const mpd_t *dec, int fmt)
942 {
943     char *r, *s;
944     mpd_ssize_t size;
945 
946     r = mpd_to_sci(dec, fmt);
947     size = mpd_to_sci_size(&s, dec, fmt);
948 
949     if (r == NULL) {
950         ASSERT(size == -1)
951         ASSERT(s == NULL)
952     }
953     else {
954         ASSERT(strcmp(r, s) == 0)
955         ASSERT(size == (mpd_ssize_t)strlen(s))
956     }
957 
958     mpd_free(s);
959     return r;
960 }
961 
962 /*
963  * Test a function returning pointer to char, accepting:
964  *     op1, context
965  *
966  * This function is used for "toSci", "toEng" and "apply"
967  * and does not use a maxctx for the conversion of the operand.
968  */
969 static void
_cp_MpdCtx(char ** token,char * (* func)(const mpd_t *,int),mpd_context_t * ctx)970 _cp_MpdCtx(char **token, char *(*func)(const mpd_t *, int), mpd_context_t *ctx)
971 {
972     mpd_context_t maxctx;
973     char *calc;
974     char *expected, *expected_fail = NULL;
975     uint32_t expstatus;
976     int n;
977 
978     mpd_readcontext(&maxctx);
979 
980     mpd_context_t *workctx = ctx;
981     workctx->status = 0;
982     n = scan_1op_result(op, &expected, token, workctx);
983     _TripleTest(op, ctx, token[0]);
984 
985     /* scan expected conditions */
986     expstatus = scan_conditions(token+n);
987 
988     /* Allocation failures for mpd_set_string */
989     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
990         mpd_init_rand(tmp);
991         workctx->status = 0;
992 
993         mpd_set_alloc_fail(workctx);
994         (void)scan_1op_result(tmp, &expected_fail, token, workctx);
995         mpd_set_alloc(workctx);
996 
997         if (!(workctx->status&MPD_Malloc_error)) {
998             break;
999         }
1000         ASSERT(mpd_isnan(tmp))
1001     }
1002     ASSERT(strcmp(expected, expected_fail) == 0)
1003     ASSERT(mpd_cmp_total(tmp, op) == 0)
1004 
1005 
1006     /* make a copy of the operand */
1007     mpd_init_rand(tmp);
1008     mpd_copy(tmp, op, workctx);
1009 
1010     calc = func(tmp, 1);
1011 
1012     /* compare the calculated result to the expected result */
1013     compare_expected(calc, expected, expstatus, token[0], workctx);
1014     mpd_free(calc);
1015     check_equalmem(tmp, op, token[0]);
1016 
1017     /* Allocation failures */
1018     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
1019         mpd_init_rand(tmp);
1020         mpd_copy(tmp, op, workctx);
1021 
1022         mpd_set_alloc_fail(workctx);
1023         calc = func(tmp, 1);
1024         mpd_set_alloc(workctx);
1025 
1026         if (calc != NULL) {
1027             break;
1028         }
1029     }
1030     compare_expected(calc, expected, expstatus, token[0], workctx);
1031     mpd_free(calc);
1032     check_equalmem(tmp, op, token[0]);
1033 }
1034 
1035 /* Test mpd_to_sci_size() and mpd_to_eng_size(). */
1036 static void
sci_eng_size(char ** token,mpd_ssize_t (* func)(char **,const mpd_t *,int),mpd_context_t * ctx)1037 sci_eng_size(char **token, mpd_ssize_t (*func)(char **, const mpd_t *, int), mpd_context_t *ctx)
1038 {
1039     mpd_context_t maxctx;
1040     char *calc;
1041     char *expected, *expected_fail = NULL;
1042     uint32_t expstatus;
1043     mpd_ssize_t size;
1044     int n;
1045 
1046     mpd_readcontext(&maxctx);
1047 
1048     mpd_context_t *workctx = ctx;
1049     workctx->status = 0;
1050     n = scan_1op_result(op, &expected, token, workctx);
1051     _TripleTest(op, ctx, token[0]);
1052 
1053     /* scan expected conditions */
1054     expstatus = scan_conditions(token+n);
1055 
1056     /* Allocation failures for mpd_set_string */
1057     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
1058         mpd_init_rand(tmp);
1059         workctx->status = 0;
1060 
1061         mpd_set_alloc_fail(workctx);
1062         (void)scan_1op_result(tmp, &expected_fail, token, workctx);
1063         mpd_set_alloc(workctx);
1064 
1065         if (!(workctx->status&MPD_Malloc_error)) {
1066             break;
1067         }
1068         ASSERT(mpd_isnan(tmp))
1069     }
1070     ASSERT(strcmp(expected, expected_fail) == 0)
1071     ASSERT(mpd_cmp_total(tmp, op) == 0)
1072 
1073 
1074     /* make a copy of the operand */
1075     mpd_init_rand(tmp);
1076     mpd_copy(tmp, op, workctx);
1077 
1078     size = func(&calc, tmp, 1);
1079     ASSERT(size == (mpd_ssize_t)strlen(calc))
1080 
1081     /* compare the calculated result to the expected result */
1082     compare_expected(calc, expected, expstatus, token[0], workctx);
1083     mpd_free(calc);
1084     check_equalmem(tmp, op, token[0]);
1085 
1086     /* Allocation failures */
1087     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
1088         mpd_init_rand(tmp);
1089         mpd_copy(tmp, op, workctx);
1090 
1091         mpd_set_alloc_fail(workctx);
1092         size = func(&calc, tmp, 1);
1093         mpd_set_alloc(workctx);
1094 
1095         if (calc != NULL) {
1096             ASSERT(size == (mpd_ssize_t)strlen(calc))
1097             break;
1098         }
1099     }
1100     compare_expected(calc, expected, expstatus, token[0], workctx);
1101     mpd_free(calc);
1102     check_equalmem(tmp, op, token[0]);
1103 }
1104 
1105 /* Quick and dirty: parse hex escape sequences */
1106 static char *
parse_escapes(const char * s)1107 parse_escapes(const char *s)
1108 {
1109     char hex[5];
1110     char *res, *cp;
1111     unsigned int u;
1112     int n;
1113 
1114     cp = res = malloc(strlen(s)+1);
1115     if (res == NULL) {
1116         return NULL;
1117     }
1118 
1119     hex[0] = '0';
1120     hex[1] = '\0';
1121     while (*s) {
1122         if (*s == '\\' && *(s+1) == 'x') {
1123             for (n = 1; n < 4; n++) {
1124                 if (!s[n]) {
1125                     free(res);
1126                     return NULL;
1127                 }
1128                 hex[n] = s[n];
1129             }
1130             hex[n] = '\0';
1131             sscanf(hex, "%x%n", &u, &n);
1132             *cp++ = (char)u;
1133             s += n;
1134         }
1135         else {
1136             *cp++ = *s++;
1137         }
1138     }
1139 
1140     *cp = '\0';
1141     return res;
1142 }
1143 
1144 /*
1145  * Test a function returning pointer to char, accepting:
1146  *     op1, fmt, context
1147  *
1148  * This function is used for "mpd_format".
1149  */
1150 static void
_cp_MpdFmtCtx(char ** token,char * (* func)(const mpd_t *,const char *,mpd_context_t *),mpd_context_t * ctx)1151 _cp_MpdFmtCtx(char **token, char *(*func)(const mpd_t *, const char *, mpd_context_t *), mpd_context_t *ctx)
1152 {
1153     mpd_context_t maxctx;
1154     char *fmt;
1155     char *calc;
1156     char *expected;
1157     uint32_t expstatus;
1158     int n;
1159 
1160     mpd_readcontext(&maxctx);
1161     maxctx.traps = MPD_Malloc_error;
1162 
1163     /* conversion should be done as if there were no limits */
1164     n = scan_1op_str_result(op1, &fmt, &expected, token, &maxctx);
1165     _TripleTest(op1, ctx, token[0]);
1166 
1167     fmt = parse_escapes(fmt);
1168     expected = parse_escapes(expected);
1169 
1170     expstatus = scan_conditions(token+n);
1171 
1172     mpd_init_rand(tmp);
1173     mpd_copy(tmp, op1, ctx);
1174     ctx->status = 0;
1175 
1176     calc = func(tmp, fmt, ctx);
1177 
1178     /* compare the calculated result to the expected result */
1179     if (calc == NULL) {
1180         compare_expected("NULL", expected, expstatus, token[0], ctx);
1181     }
1182     else {
1183         compare_expected(calc, expected, expstatus, token[0], ctx);
1184         mpd_free(calc);
1185     }
1186     check_equalmem(tmp, op1, token[0]);
1187 
1188     /* Allocation failures */
1189     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
1190         mpd_init_rand(tmp);
1191         mpd_copy(tmp, op1, ctx);
1192         ctx->status = 0;
1193 
1194         mpd_set_alloc_fail(ctx);
1195         calc = func(tmp, fmt, ctx);
1196         mpd_set_alloc(ctx);
1197         if (!(ctx->status&MPD_Malloc_error)) {
1198             break;
1199         }
1200         ASSERT(calc == NULL)
1201     }
1202     if (calc == NULL) {
1203         compare_expected("NULL", expected, expstatus, token[0], ctx);
1204     }
1205     else {
1206         compare_expected(calc, expected, expstatus, token[0], ctx);
1207         mpd_free(calc);
1208     }
1209     check_equalmem(tmp, op1, token[0]);
1210 
1211     free(fmt);
1212     free(expected);
1213 }
1214 
1215 /*
1216  * Test a function returning pointer to const char, accepting:
1217  *     op1, context
1218  */
1219 static void
_ccp_MpdCtx(char ** token,const char * (* func)(const mpd_t *,const mpd_context_t *),mpd_context_t * ctx)1220 _ccp_MpdCtx(char **token, const char *(*func)(const mpd_t *, const mpd_context_t *), mpd_context_t *ctx)
1221 {
1222     mpd_context_t maxctx;
1223     const char *calc;
1224     char *expected;
1225     uint32_t expstatus;
1226     int n;
1227 
1228     mpd_readcontext(&maxctx);
1229     maxctx.traps = MPD_Malloc_error;
1230 
1231     /* conversion should be done as if there were no limits */
1232     n = scan_1op_result(op, &expected, token, &maxctx);
1233     _TripleTest(op, ctx, token[0]);
1234 
1235     /* scan expected conditions */
1236     expstatus = scan_conditions(token+n);
1237 
1238 
1239     mpd_init_rand(tmp);
1240     mpd_copy(tmp, op, ctx);
1241     ctx->status = 0;
1242 
1243     calc = func(tmp, ctx);
1244 
1245     compare_expected(calc, expected, expstatus, token[0], ctx);
1246     check_equalmem(tmp, op, token[0]);
1247 
1248     /* Allocation failures */
1249     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
1250         mpd_init_rand(tmp);
1251         mpd_copy(tmp, op, ctx);
1252         ctx->status = 0;
1253 
1254         mpd_set_alloc_fail(ctx);
1255         calc = func(tmp, ctx);
1256         mpd_set_alloc(ctx);
1257         if (!(ctx->status&MPD_Malloc_error)) {
1258             break;
1259         }
1260         ASSERT(calc == NULL)
1261     }
1262     compare_expected(calc, expected, expstatus, token[0], ctx);
1263     check_equalmem(tmp, op, token[0]);
1264 }
1265 
1266 /* Test a unary function */
1267 static void
_Res_Op_Ctx(char * token[],void (* func)(mpd_t *,const mpd_t *,mpd_context_t *),mpd_context_t * ctx)1268 _Res_Op_Ctx(char *token[], void (*func)(mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
1269 {
1270     mpd_context_t maxctx;
1271     char *calc;
1272     char *expected;
1273     uint32_t expstatus;
1274     int n, incr;
1275 
1276     mpd_readcontext(&maxctx);
1277     maxctx.traps = MPD_Malloc_error;
1278 
1279     n = scan_1op_result(op, &expected, token, &maxctx);
1280     _TripleTest(op, ctx, token[0]);
1281 
1282     /* scan expected conditions */
1283     expstatus = scan_conditions(token+n);
1284 
1285 
1286     /* result and tmp are distinct decimals */
1287     mpd_init_rand(tmp);
1288     mpd_copy(tmp, op, ctx);
1289     mpd_init_rand(result);
1290     ctx->status = 0;
1291 
1292     mpd_set_alloc_count(ctx);
1293     func(result, tmp, ctx);
1294     mpd_set_alloc(ctx);
1295 
1296     calc = _mpd_to_sci(result, 1);
1297     compare_expected(calc, expected, expstatus, token[0], ctx);
1298     mpd_free(calc);
1299     check_equalmem(tmp, op, token[0]);
1300 
1301     /* Allocation failures */
1302     incr = 1;
1303     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
1304         mpd_init_rand(tmp);
1305         mpd_copy(tmp, op, ctx);
1306         mpd_minalloc(result);
1307         ctx->status = 0;
1308 
1309         mpd_set_alloc_fail(ctx);
1310         func(result, tmp, ctx);
1311         mpd_set_alloc(ctx);
1312 
1313         if (!(ctx->status&MPD_Malloc_error)) {
1314             break;
1315         }
1316         ASSERT(mpd_isnan(result))
1317 
1318         if (alloc_fail > 100) {
1319             incr = (int)(alloc_count*0.02) + 1;
1320         }
1321     }
1322     calc = _mpd_to_sci(result, 1);
1323     compare_expected(calc, expected, expstatus, token[0], ctx);
1324     mpd_free(calc);
1325     check_equalmem(tmp, op, token[0]);
1326 
1327 
1328     /* result equals operand */
1329     mpd_init_rand(tmp);
1330     mpd_copy(tmp, op, ctx);
1331     ctx->status = 0;
1332 
1333     mpd_set_alloc_count(ctx);
1334     func(tmp, tmp, ctx);
1335     mpd_set_alloc(ctx);
1336 
1337     calc = _mpd_to_sci(tmp, 1);
1338     compare_expected(calc, expected, expstatus, token[0], ctx);
1339     mpd_free(calc);
1340 
1341     /* Allocation failures */
1342     incr = 1;
1343     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
1344         mpd_init_rand(tmp);
1345         mpd_copy(tmp, op, ctx);
1346         ctx->status = 0;
1347 
1348         mpd_set_alloc_fail(ctx);
1349         func(tmp, tmp, ctx);
1350         mpd_set_alloc(ctx);
1351 
1352         if (!(ctx->status&MPD_Malloc_error)) {
1353             break;
1354         }
1355         ASSERT(mpd_isnan(tmp))
1356 
1357         if (alloc_fail > 100) {
1358             incr = (int)(alloc_count*0.02) + 1;
1359         }
1360     }
1361     calc = _mpd_to_sci(tmp, 1);
1362     compare_expected(calc, expected, expstatus, token[0], ctx);
1363     mpd_free(calc);
1364 }
1365 
1366 /* Test a unary function, quantize the operand before applying the actual function */
1367 static void
_Res_Op_CtxWithQuantize(char * token[],void (* func)(mpd_t *,const mpd_t *,mpd_context_t *),mpd_context_t * ctx)1368 _Res_Op_CtxWithQuantize(char *token[], void (*func)(mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
1369 {
1370     mpd_context_t maxctx;
1371     char *calc;
1372     char *expected;
1373     uint32_t expstatus;
1374     int n, incr;
1375 
1376     mpd_readcontext(&maxctx);
1377     maxctx.traps = MPD_Malloc_error;
1378 
1379     n = scan_2ops_result(op, op1, &expected, token, &maxctx);
1380     mpd_quantize(op, op, op1, &maxctx);
1381     _TripleTest(op, ctx, token[0]);
1382     _TripleTest(op1, ctx, token[0]);
1383 
1384     /* scan expected conditions */
1385     expstatus = scan_conditions(token+n);
1386 
1387 
1388     /* result and tmp are distinct decimals */
1389     mpd_init_rand(tmp);
1390     mpd_copy(tmp, op, ctx);
1391     mpd_init_rand(result);
1392     ctx->status = 0;
1393 
1394     mpd_set_alloc_count(ctx);
1395     func(result, tmp, ctx);
1396     mpd_set_alloc(ctx);
1397 
1398     calc = _mpd_to_sci(result, 1);
1399     compare_expected(calc, expected, expstatus, token[0], ctx);
1400     mpd_free(calc);
1401     check_equalmem(tmp, op, token[0]);
1402 
1403     /* Allocation failures */
1404     incr = 1;
1405     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
1406         mpd_init_rand(tmp);
1407         mpd_copy(tmp, op, ctx);
1408         mpd_minalloc(result);
1409         ctx->status = 0;
1410 
1411         mpd_set_alloc_fail(ctx);
1412         func(result, tmp, ctx);
1413         mpd_set_alloc(ctx);
1414 
1415         if (!(ctx->status&MPD_Malloc_error)) {
1416             break;
1417         }
1418         ASSERT(mpd_isnan(result))
1419 
1420         if (alloc_fail > 50) {
1421             incr = (int)(alloc_count*0.02) + 1;
1422         }
1423     }
1424     calc = _mpd_to_sci(result, 1);
1425     compare_expected(calc, expected, expstatus, token[0], ctx);
1426     mpd_free(calc);
1427     check_equalmem(tmp, op, token[0]);
1428 
1429 
1430     /* result equals operand */
1431     mpd_init_rand(tmp);
1432     mpd_copy(tmp, op, ctx);
1433     ctx->status = 0;
1434 
1435     mpd_set_alloc_count(ctx);
1436     func(tmp, tmp, ctx);
1437     mpd_set_alloc(ctx);
1438 
1439     calc = _mpd_to_sci(tmp, 1);
1440     compare_expected(calc, expected, expstatus, token[0], ctx);
1441     mpd_free(calc);
1442 
1443     /* Allocation failures */
1444     incr = 1;
1445     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
1446         mpd_init_rand(tmp);
1447         mpd_copy(tmp, op, ctx);
1448         ctx->status = 0;
1449 
1450         mpd_set_alloc_fail(ctx);
1451         func(tmp, tmp, ctx);
1452         mpd_set_alloc(ctx);
1453 
1454         if (!(ctx->status&MPD_Malloc_error)) {
1455             break;
1456         }
1457         ASSERT(mpd_isnan(tmp))
1458 
1459         if (alloc_fail > 50) {
1460             incr = (int)(alloc_count*0.02) + 1;
1461         }
1462     }
1463     calc = _mpd_to_sci(tmp, 1);
1464     compare_expected(calc, expected, expstatus, token[0], ctx);
1465     mpd_free(calc);
1466 }
1467 
1468 static void
resolve_status_hack(uint32_t * expstatus,const uint32_t status)1469 resolve_status_hack(uint32_t *expstatus, const uint32_t status)
1470 {
1471     /* hack #1 to resolve disagreement with results generated by decimal.py */
1472     if ((*expstatus & MPD_Invalid_operation) &&
1473         (status & MPD_Division_impossible)) {
1474         *expstatus = MPD_Division_impossible;
1475     }
1476 
1477     /* hack #2 to resolve disagreement with results generated by decimal.py */
1478     if ((*expstatus & MPD_Invalid_operation) &&
1479         (status & MPD_Division_undefined)) {
1480         *expstatus = MPD_Division_undefined;
1481     }
1482 }
1483 
1484 /* Test a binary function */
1485 static void
_Res_Binop_Ctx(char * token[],void (* func)(mpd_t *,const mpd_t *,const mpd_t *,mpd_context_t *),mpd_context_t * ctx)1486 _Res_Binop_Ctx(char *token[], void (*func)(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *),
1487                mpd_context_t *ctx)
1488 {
1489     mpd_context_t maxctx;
1490     char *calc;
1491     char *expected;
1492     uint32_t expstatus;
1493     int n, incr;
1494 
1495     mpd_readcontext(&maxctx);
1496     maxctx.traps = MPD_Malloc_error;
1497 
1498     n = scan_2ops_result(op1, op2, &expected, token, &maxctx);
1499     _TripleTest(op1, ctx, token[0]);
1500     _TripleTest(op2, ctx, token[0]);
1501 
1502     /* scan expected conditions */
1503     expstatus = scan_conditions(token+n);
1504 
1505     /* three distinct decimals */
1506     mpd_init_rand(tmp1);
1507     mpd_init_rand(tmp2);
1508     mpd_copy(tmp1, op1, ctx);
1509     mpd_copy(tmp2, op2, ctx);
1510     mpd_init_rand(result);
1511     ctx->status = 0;
1512 
1513     mpd_set_alloc_count(ctx);
1514     func(result, tmp1, tmp2, ctx);
1515     mpd_set_alloc(ctx);
1516 
1517     calc = _mpd_to_sci(result, 1);
1518     compare_expected(calc, expected, expstatus, token[0], ctx);
1519     mpd_free(calc);
1520     check_equalmem(tmp1, op1, token[0]);
1521     check_equalmem(tmp2, op2, token[0]);
1522 
1523     /* Allocation failures */
1524     incr = 1;
1525     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
1526         mpd_init_rand(tmp1);
1527         mpd_init_rand(tmp2);
1528         mpd_copy(tmp1, op1, ctx);
1529         mpd_copy(tmp2, op2, ctx);
1530         mpd_minalloc(result);
1531         ctx->status = 0;
1532 
1533         mpd_set_alloc_fail(ctx);
1534         func(result, tmp1, tmp2, ctx);
1535         mpd_set_alloc(ctx);
1536 
1537         if (!(ctx->status&MPD_Malloc_error)) {
1538             break;
1539         }
1540         ASSERT(mpd_isnan(result))
1541 
1542         if (alloc_fail > 50) {
1543             incr = (int)(alloc_count*0.02) + 1;
1544         }
1545     }
1546     calc = _mpd_to_sci(result, 1);
1547     compare_expected(calc, expected, expstatus, token[0], ctx);
1548     mpd_free(calc);
1549     check_equalmem(tmp1, op1, token[0]);
1550     check_equalmem(tmp2, op2, token[0]);
1551 
1552 
1553     /* result == tmp1 */
1554     mpd_init_rand(tmp1);
1555     mpd_init_rand(tmp2);
1556     mpd_copy(tmp1, op1, ctx);
1557     mpd_copy(tmp2, op2, ctx);
1558     ctx->status = 0;
1559 
1560     mpd_set_alloc_count(ctx);
1561     func(tmp1, tmp1, tmp2, ctx);
1562     mpd_set_alloc(ctx);
1563 
1564     calc = _mpd_to_sci(tmp1, 1);
1565     compare_expected(calc, expected, expstatus, token[0], ctx);
1566     mpd_free(calc);
1567     check_equalmem(tmp2, op2, token[0]);
1568 
1569     /* Allocation failures */
1570     incr = 1;
1571     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
1572         mpd_init_rand(tmp1);
1573         mpd_init_rand(tmp2);
1574         mpd_copy(tmp1, op1, ctx);
1575         mpd_copy(tmp2, op2, ctx);
1576         ctx->status = 0;
1577 
1578         mpd_set_alloc_fail(ctx);
1579         func(tmp1, tmp1, tmp2, ctx);
1580         mpd_set_alloc(ctx);
1581 
1582         if (!(ctx->status&MPD_Malloc_error)) {
1583             break;
1584         }
1585         ASSERT(mpd_isnan(tmp1))
1586 
1587         if (alloc_fail > 50) {
1588             incr = (int)(alloc_count*0.02) + 1;
1589         }
1590     }
1591     calc = _mpd_to_sci(tmp1, 1);
1592     compare_expected(calc, expected, expstatus, token[0], ctx);
1593     mpd_free(calc);
1594     check_equalmem(tmp2, op2, token[0]);
1595 
1596 
1597     /* result == tmp2 */
1598     mpd_init_rand(tmp1);
1599     mpd_init_rand(tmp2);
1600     mpd_copy(tmp1, op1, ctx);
1601     mpd_copy(tmp2, op2, ctx);
1602     ctx->status = 0;
1603 
1604     mpd_set_alloc_count(ctx);
1605     func(tmp2, tmp1, tmp2, ctx);
1606     mpd_set_alloc(ctx);
1607 
1608     calc = _mpd_to_sci(tmp2, 1);
1609     compare_expected(calc, expected, expstatus, token[0], ctx);
1610     mpd_free(calc);
1611     check_equalmem(tmp1, op1, token[0]);
1612 
1613     /* Allocation failures */
1614     incr = 1;
1615     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
1616         mpd_init_rand(tmp1);
1617         mpd_init_rand(tmp2);
1618         mpd_copy(tmp1, op1, ctx);
1619         mpd_copy(tmp2, op2, ctx);
1620         ctx->status = 0;
1621 
1622         mpd_set_alloc_fail(ctx);
1623         func(tmp2, tmp1, tmp2, ctx);
1624         mpd_set_alloc(ctx);
1625 
1626         if (!(ctx->status&MPD_Malloc_error)) {
1627             break;
1628         }
1629         ASSERT(mpd_isnan(tmp2))
1630 
1631         if (alloc_fail > 50) {
1632             incr = (int)(alloc_count*0.02) + 1;
1633         }
1634     }
1635     calc = _mpd_to_sci(tmp2, 1);
1636     compare_expected(calc, expected, expstatus, token[0], ctx);
1637     mpd_free(calc);
1638     check_equalmem(tmp1, op1, token[0]);
1639 }
1640 
1641 /* Test a binary function where op1 == op2. */
1642 static void
_Res_EqualBinop_Ctx(char * token[],void (* func)(mpd_t *,const mpd_t *,const mpd_t *,mpd_context_t *),mpd_context_t * ctx)1643 _Res_EqualBinop_Ctx(char *token[], void (*func)(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *),
1644                     mpd_context_t *ctx)
1645 {
1646     mpd_context_t maxctx;
1647     char *calc;
1648     char *expected;
1649     uint32_t expstatus;
1650     int n;
1651 
1652     mpd_readcontext(&maxctx);
1653     maxctx.traps = MPD_Malloc_error;
1654 
1655     n = scan_1op_result(op, &expected, token, &maxctx);
1656     _TripleTest(op, ctx, token[0]);
1657 
1658     /* scan expected conditions */
1659     expstatus = scan_conditions(token+n);
1660 
1661 
1662     /* equal operands, distinct result */
1663     mpd_init_rand(tmp);
1664     mpd_copy(tmp, op, ctx);
1665     mpd_init_rand(result);
1666     ctx->status = 0;
1667 
1668     func(result, tmp, tmp, ctx);
1669 
1670     calc = _mpd_to_sci(result, 1);
1671     compare_expected(calc, expected, expstatus, token[0], ctx);
1672     mpd_free(calc);
1673     check_equalmem(tmp, op, token[0]);
1674 
1675     /* Allocation failures */
1676     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
1677         mpd_init_rand(tmp);
1678         mpd_copy(tmp, op, ctx);
1679         mpd_minalloc(result);
1680         ctx->status = 0;
1681 
1682         mpd_set_alloc_fail(ctx);
1683         func(result, tmp, tmp, ctx);
1684         mpd_set_alloc(ctx);
1685 
1686         if (!(ctx->status&MPD_Malloc_error)) {
1687             break;
1688         }
1689         ASSERT(mpd_isnan(result))
1690     }
1691     calc = _mpd_to_sci(result, 1);
1692     compare_expected(calc, expected, expstatus, token[0], ctx);
1693     mpd_free(calc);
1694     check_equalmem(tmp, op, token[0]);
1695 
1696 
1697     /* all parameters equal */
1698     mpd_init_rand(tmp);
1699     mpd_copy(tmp, op, ctx);
1700     ctx->status = 0;
1701 
1702     func(tmp, tmp, tmp, ctx);
1703 
1704     calc = _mpd_to_sci(tmp, 1);
1705     compare_expected(calc, expected, expstatus, token[0], ctx);
1706     mpd_free(calc);
1707 
1708     /* Allocation failures */
1709     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
1710         mpd_init_rand(tmp);
1711         mpd_copy(tmp, op, ctx);
1712         ctx->status = 0;
1713 
1714         mpd_set_alloc_fail(ctx);
1715         func(tmp, tmp, tmp, ctx);
1716         mpd_set_alloc(ctx);
1717         if (!(ctx->status&MPD_Malloc_error)) {
1718             break;
1719         }
1720         ASSERT(mpd_isnan(tmp))
1721     }
1722     calc = _mpd_to_sci(tmp, 1);
1723     compare_expected(calc, expected, expstatus, token[0], ctx);
1724     mpd_free(calc);
1725 }
1726 
1727 /* Test a binary function with a binary result */
1728 static void
_Binres_Binop_Ctx(char * token[],void (* func)(mpd_t *,mpd_t *,const mpd_t *,const mpd_t *,mpd_context_t *),mpd_context_t * ctx)1729 _Binres_Binop_Ctx(char *token[], void (*func)(mpd_t *, mpd_t*, const mpd_t *, const mpd_t *, mpd_context_t *),
1730                   mpd_context_t *ctx)
1731 {
1732     mpd_context_t maxctx;
1733     char *calc;
1734     char *expected1, *expected2;
1735     uint32_t expstatus;
1736     int n, incr;
1737 
1738     mpd_readcontext(&maxctx);
1739     maxctx.traps = MPD_Malloc_error;
1740 
1741     n = scan_2ops_2results(op1, op2, &expected1, &expected2, token, &maxctx);
1742     _TripleTest(op1, ctx, token[0]);
1743     _TripleTest(op2, ctx, token[0]);
1744 
1745     /* scan expected conditions */
1746     expstatus = scan_conditions(token+n);
1747 
1748 
1749     /* four distinct decimals */
1750     mpd_init_rand(tmp1);
1751     mpd_init_rand(tmp2);
1752     mpd_copy(tmp1, op1, ctx);
1753     mpd_copy(tmp2, op2, ctx);
1754     mpd_init_rand(result1);
1755     mpd_init_rand(result2);
1756     ctx->status = 0;
1757 
1758     mpd_set_alloc_count(ctx);
1759     func(result1, result2, tmp1, tmp2, ctx);
1760     mpd_set_alloc(ctx);
1761 
1762     resolve_status_hack(&expstatus, ctx->status);
1763 
1764     calc = _mpd_to_sci(result1, 1);
1765     compare_expected(calc, expected1, expstatus, token[0], ctx);
1766     mpd_free(calc);
1767 
1768     calc = _mpd_to_sci(result2, 1);
1769     compare_expected(calc, expected2, expstatus, token[0], ctx);
1770     mpd_free(calc);
1771 
1772     check_equalmem(tmp1, op1, token[0]);
1773     check_equalmem(tmp2, op2, token[0]);
1774 
1775     /* Allocation failures */
1776     incr = 1;
1777     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
1778         mpd_init_rand(tmp1);
1779         mpd_init_rand(tmp2);
1780         mpd_copy(tmp1, op1, ctx);
1781         mpd_copy(tmp2, op2, ctx);
1782         mpd_minalloc(result1);
1783         mpd_minalloc(result2);
1784         ctx->status = 0;
1785 
1786         mpd_set_alloc_fail(ctx);
1787         func(result1, result2, tmp1, tmp2, ctx);
1788         mpd_set_alloc(ctx);
1789 
1790         if (!(ctx->status&MPD_Malloc_error)) {
1791             break;
1792         }
1793         ASSERT(mpd_isnan(result1))
1794         ASSERT(mpd_isnan(result2))
1795 
1796         if (alloc_fail > 50) {
1797             incr = (int)(alloc_count*0.02) + 1;
1798         }
1799     }
1800     calc = _mpd_to_sci(result1, 1);
1801     compare_expected(calc, expected1, expstatus, token[0], ctx);
1802     mpd_free(calc);
1803 
1804     calc = _mpd_to_sci(result2, 1);
1805     compare_expected(calc, expected2, expstatus, token[0], ctx);
1806     mpd_free(calc);
1807 
1808     check_equalmem(tmp1, op1, token[0]);
1809     check_equalmem(tmp2, op2, token[0]);
1810 
1811 
1812     /* result1 == tmp1 */
1813     mpd_init_rand(tmp1);
1814     mpd_init_rand(tmp2);
1815     mpd_copy(tmp1, op1, ctx);
1816     mpd_copy(tmp2, op2, ctx);
1817     mpd_init_rand(result2);
1818     ctx->status = 0;
1819 
1820     mpd_set_alloc_count(ctx);
1821     func(tmp1, result2, tmp1, tmp2, ctx);
1822     mpd_set_alloc(ctx);
1823 
1824     calc = _mpd_to_sci(tmp1, 1);
1825     compare_expected(calc, expected1, expstatus, token[0], ctx);
1826     mpd_free(calc);
1827 
1828     calc = _mpd_to_sci(result2, 1);
1829     compare_expected(calc, expected2, expstatus, token[0], ctx);
1830     mpd_free(calc);
1831 
1832     check_equalmem(tmp2, op2, token[0]);
1833 
1834     /* Allocation failures */
1835     incr = 1;
1836     for (alloc_fail = 1; alloc_fail <= INT_MAX; alloc_fail += incr) {
1837         mpd_init_rand(tmp1);
1838         mpd_init_rand(tmp2);
1839         mpd_copy(tmp1, op1, ctx);
1840         mpd_copy(tmp2, op2, ctx);
1841         mpd_minalloc(result2);
1842         ctx->status = 0;
1843 
1844         mpd_set_alloc_fail(ctx);
1845         func(tmp1, result2, tmp1, tmp2, ctx);
1846         mpd_set_alloc(ctx);
1847 
1848         if (!(ctx->status&MPD_Malloc_error)) {
1849             break;
1850         }
1851         ASSERT(mpd_isnan(tmp1))
1852         ASSERT(mpd_isnan(result2))
1853 
1854         if (alloc_fail > 50) {
1855             incr = (int)(alloc_count*0.02) + 1;
1856         }
1857     }
1858     calc = _mpd_to_sci(tmp1, 1);
1859     compare_expected(calc, expected1, expstatus, token[0], ctx);
1860     mpd_free(calc);
1861 
1862     calc = _mpd_to_sci(result2, 1);
1863     compare_expected(calc, expected2, expstatus, token[0], ctx);
1864     mpd_free(calc);
1865 
1866     check_equalmem(tmp2, op2, token[0]);
1867 
1868 
1869     /* result2 == tmp1 */
1870     mpd_init_rand(tmp1);
1871     mpd_init_rand(tmp2);
1872     mpd_copy(tmp1, op1, ctx);
1873     mpd_copy(tmp2, op2, ctx);
1874     mpd_init_rand(result1);
1875     ctx->status = 0;
1876 
1877     mpd_set_alloc_count(ctx);
1878     func(result1, tmp1, tmp1, tmp2, ctx);
1879     mpd_set_alloc(ctx);
1880 
1881     calc = _mpd_to_sci(result1, 1);
1882     compare_expected(calc, expected1, expstatus, token[0], ctx);
1883     mpd_free(calc);
1884 
1885     calc = _mpd_to_sci(tmp1, 1);
1886     compare_expected(calc, expected2, expstatus, token[0], ctx);
1887     mpd_free(calc);
1888 
1889     check_equalmem(tmp2, op2, token[0]);
1890 
1891     /* Allocation failures */
1892     incr = 1;
1893     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
1894         mpd_init_rand(tmp1);
1895         mpd_init_rand(tmp2);
1896         mpd_copy(tmp1, op1, ctx);
1897         mpd_copy(tmp2, op2, ctx);
1898         mpd_minalloc(result1);
1899         ctx->status = 0;
1900 
1901         mpd_set_alloc_fail(ctx);
1902         func(result1, tmp1, tmp1, tmp2, ctx);
1903         mpd_set_alloc(ctx);
1904 
1905         if (!(ctx->status&MPD_Malloc_error)) {
1906             break;
1907         }
1908         ASSERT(mpd_isnan(result1))
1909         ASSERT(mpd_isnan(tmp1))
1910 
1911         if (alloc_fail > 50) {
1912             incr = (int)(alloc_count*0.02) + 1;
1913         }
1914     }
1915     calc = _mpd_to_sci(result1, 1);
1916     compare_expected(calc, expected1, expstatus, token[0], ctx);
1917     mpd_free(calc);
1918 
1919     calc = _mpd_to_sci(tmp1, 1);
1920     compare_expected(calc, expected2, expstatus, token[0], ctx);
1921     mpd_free(calc);
1922 
1923     check_equalmem(tmp2, op2, token[0]);
1924 
1925 
1926     /* result1 == tmp2 */
1927     mpd_init_rand(tmp1);
1928     mpd_init_rand(tmp2);
1929     mpd_copy(tmp1, op1, ctx);
1930     mpd_copy(tmp2, op2, ctx);
1931     mpd_init_rand(result2);
1932     ctx->status = 0;
1933 
1934     mpd_set_alloc_count(ctx);
1935     func(tmp2, result2, tmp1, tmp2, ctx);
1936     mpd_set_alloc(ctx);
1937 
1938     calc = _mpd_to_sci(tmp2, 1);
1939     compare_expected(calc, expected1, expstatus, token[0], ctx);
1940     mpd_free(calc);
1941 
1942     calc = _mpd_to_sci(result2, 1);
1943     compare_expected(calc, expected2, expstatus, token[0], ctx);
1944     mpd_free(calc);
1945 
1946     check_equalmem(tmp1, op1, token[0]);
1947 
1948     /* Allocation failures */
1949     incr = 1;
1950     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
1951         mpd_init_rand(tmp1);
1952         mpd_init_rand(tmp2);
1953         mpd_copy(tmp1, op1, ctx);
1954         mpd_copy(tmp2, op2, ctx);
1955         mpd_minalloc(result2);
1956         ctx->status = 0;
1957 
1958         mpd_set_alloc_fail(ctx);
1959         func(tmp2, result2, tmp1, tmp2, ctx);
1960         mpd_set_alloc(ctx);
1961 
1962         if (!(ctx->status&MPD_Malloc_error)) {
1963             break;
1964         }
1965         ASSERT(mpd_isnan(tmp2))
1966         ASSERT(mpd_isnan(result2))
1967 
1968         if (alloc_fail > 50) {
1969             incr = (int)(alloc_count*0.02) + 1;
1970         }
1971     }
1972     calc = _mpd_to_sci(tmp2, 1);
1973     compare_expected(calc, expected1, expstatus, token[0], ctx);
1974     mpd_free(calc);
1975 
1976     calc = _mpd_to_sci(result2, 1);
1977     compare_expected(calc, expected2, expstatus, token[0], ctx);
1978     mpd_free(calc);
1979 
1980     check_equalmem(tmp1, op1, token[0]);
1981 
1982 
1983     /* result2 == tmp2 */
1984     mpd_init_rand(tmp1);
1985     mpd_init_rand(tmp2);
1986     mpd_copy(tmp1, op1, ctx);
1987     mpd_copy(tmp2, op2, ctx);
1988     mpd_init_rand(result1);
1989     ctx->status = 0;
1990 
1991     mpd_set_alloc_count(ctx);
1992     func(result1, tmp2, tmp1, tmp2, ctx);
1993     mpd_set_alloc(ctx);
1994 
1995     calc = _mpd_to_sci(result1, 1);
1996     compare_expected(calc, expected1, expstatus, token[0], ctx);
1997     mpd_free(calc);
1998 
1999     calc = _mpd_to_sci(tmp2, 1);
2000     compare_expected(calc, expected2, expstatus, token[0], ctx);
2001     mpd_free(calc);
2002 
2003     check_equalmem(tmp1, op1, token[0]);
2004 
2005     /* Allocation failures */
2006     incr = 1;
2007     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
2008         mpd_init_rand(tmp1);
2009         mpd_init_rand(tmp2);
2010         mpd_copy(tmp1, op1, ctx);
2011         mpd_copy(tmp2, op2, ctx);
2012         mpd_minalloc(result1);
2013         ctx->status = 0;
2014 
2015         mpd_set_alloc_fail(ctx);
2016         func(result1, tmp2, tmp1, tmp2, ctx);
2017         mpd_set_alloc(ctx);
2018 
2019         if (!(ctx->status&MPD_Malloc_error)) {
2020             break;
2021         }
2022         ASSERT(mpd_isnan(result1))
2023         ASSERT(mpd_isnan(tmp2))
2024 
2025         if (alloc_fail > 50) {
2026             incr = (int)(alloc_count*0.02) + 1;
2027         }
2028     }
2029     calc = _mpd_to_sci(result1, 1);
2030     compare_expected(calc, expected1, expstatus, token[0], ctx);
2031     mpd_free(calc);
2032 
2033     calc = _mpd_to_sci(tmp2, 1);
2034     compare_expected(calc, expected2, expstatus, token[0], ctx);
2035     mpd_free(calc);
2036 
2037     check_equalmem(tmp1, op1, token[0]);
2038 
2039 
2040     /* result1 == tmp1, result2 == tmp2 */
2041     mpd_init_rand(tmp1);
2042     mpd_init_rand(tmp2);
2043     mpd_copy(tmp1, op1, ctx);
2044     mpd_copy(tmp2, op2, ctx);
2045     ctx->status = 0;
2046 
2047     mpd_set_alloc_count(ctx);
2048     func(tmp1, tmp2, tmp1, tmp2, ctx);
2049     mpd_set_alloc(ctx);
2050 
2051     calc = _mpd_to_sci(tmp1, 1);
2052     compare_expected(calc, expected1, expstatus, token[0], ctx);
2053     mpd_free(calc);
2054 
2055     calc = _mpd_to_sci(tmp2, 1);
2056     compare_expected(calc, expected2, expstatus, token[0], ctx);
2057     mpd_free(calc);
2058 
2059     /* Allocation failures */
2060     incr = 1;
2061     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
2062         mpd_init_rand(tmp1);
2063         mpd_init_rand(tmp2);
2064         mpd_copy(tmp1, op1, ctx);
2065         mpd_copy(tmp2, op2, ctx);
2066         ctx->status = 0;
2067 
2068         mpd_set_alloc_fail(ctx);
2069         func(tmp1, tmp2, tmp1, tmp2, ctx);
2070         mpd_set_alloc(ctx);
2071 
2072         if (!(ctx->status&MPD_Malloc_error)) {
2073             break;
2074         }
2075         ASSERT(mpd_isnan(tmp1))
2076         ASSERT(mpd_isnan(tmp2))
2077 
2078         if (alloc_fail > 50) {
2079             incr = (int)(alloc_count*0.02) + 1;
2080         }
2081     }
2082     calc = _mpd_to_sci(tmp1, 1);
2083     compare_expected(calc, expected1, expstatus, token[0], ctx);
2084     mpd_free(calc);
2085 
2086     calc = _mpd_to_sci(tmp2, 1);
2087     compare_expected(calc, expected2, expstatus, token[0], ctx);
2088     mpd_free(calc);
2089 
2090 
2091     /* result1 == tmp2, result2 == tmp1 */
2092     mpd_init_rand(tmp1);
2093     mpd_init_rand(tmp2);
2094     mpd_copy(tmp1, op1, ctx);
2095     mpd_copy(tmp2, op2, ctx);
2096     ctx->status = 0;
2097 
2098     mpd_set_alloc_count(ctx);
2099     func(tmp2, tmp1, tmp1, tmp2, ctx);
2100     mpd_set_alloc(ctx);
2101 
2102     calc = _mpd_to_sci(tmp2, 1);
2103     compare_expected(calc, expected1, expstatus, token[0], ctx);
2104     mpd_free(calc);
2105 
2106     calc = _mpd_to_sci(tmp1, 1);
2107     compare_expected(calc, expected2, expstatus, token[0], ctx);
2108     mpd_free(calc);
2109 
2110     /* Allocation failures */
2111     incr = 1;
2112     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
2113         mpd_init_rand(tmp1);
2114         mpd_init_rand(tmp2);
2115         mpd_copy(tmp1, op1, ctx);
2116         mpd_copy(tmp2, op2, ctx);
2117         ctx->status = 0;
2118 
2119         mpd_set_alloc_fail(ctx);
2120         func(tmp2, tmp1, tmp1, tmp2, ctx);
2121         mpd_set_alloc(ctx);
2122 
2123         if (!(ctx->status&MPD_Malloc_error)) {
2124             break;
2125         }
2126         ASSERT(mpd_isnan(tmp2))
2127         ASSERT(mpd_isnan(tmp1))
2128 
2129         if (alloc_fail > 50) {
2130             incr = (int)(alloc_count*0.02) + 1;
2131         }
2132     }
2133     calc = _mpd_to_sci(tmp2, 1);
2134     compare_expected(calc, expected1, expstatus, token[0], ctx);
2135     mpd_free(calc);
2136 
2137     calc = _mpd_to_sci(tmp1, 1);
2138     compare_expected(calc, expected2, expstatus, token[0], ctx);
2139     mpd_free(calc);
2140 }
2141 
2142 /* Test a binary function with a binary result; equal operands */
2143 static void
_Binres_EqualBinop_Ctx(char * token[],void (* func)(mpd_t *,mpd_t *,const mpd_t *,const mpd_t *,mpd_context_t *),mpd_context_t * ctx)2144 _Binres_EqualBinop_Ctx(char *token[], void (*func)(mpd_t *, mpd_t*, const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
2145 {
2146     mpd_context_t maxctx;
2147     char *calc;
2148     char *expected1, *expected2;
2149     uint32_t expstatus;
2150     int n;
2151 
2152     mpd_readcontext(&maxctx);
2153     maxctx.traps = MPD_Malloc_error;
2154 
2155     n = scan_1op_2results(op, &expected1, &expected2, token, &maxctx);
2156     _TripleTest(op, ctx, token[0]);
2157 
2158     /* scan expected conditions */
2159     expstatus = scan_conditions(token+n);
2160 
2161 
2162     /* distinct results */
2163     mpd_init_rand(tmp);
2164     mpd_copy(tmp, op, ctx);
2165     mpd_init_rand(result1);
2166     mpd_init_rand(result2);
2167     ctx->status = 0;
2168 
2169     func(result1, result2, tmp, tmp, ctx);
2170 
2171     resolve_status_hack(&expstatus, ctx->status);
2172 
2173     calc = _mpd_to_sci(result1, 1);
2174     compare_expected(calc, expected1, expstatus, token[0], ctx);
2175     mpd_free(calc);
2176 
2177     calc = _mpd_to_sci(result2, 1);
2178     compare_expected(calc, expected2, expstatus, token[0], ctx);
2179     mpd_free(calc);
2180 
2181     check_equalmem(tmp, op, token[0]);
2182 
2183     /* Allocation failures */
2184     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
2185         mpd_init_rand(tmp);
2186         mpd_copy(tmp, op, ctx);
2187         mpd_minalloc(result1);
2188         mpd_minalloc(result2);
2189         ctx->status = 0;
2190 
2191         mpd_set_alloc_fail(ctx);
2192         func(result1, result2, tmp, tmp, ctx);
2193         mpd_set_alloc(ctx);
2194 
2195         if (!(ctx->status&MPD_Malloc_error)) {
2196             break;
2197         }
2198         ASSERT(mpd_isnan(result1))
2199         ASSERT(mpd_isnan(result2))
2200     }
2201     calc = _mpd_to_sci(result1, 1);
2202     compare_expected(calc, expected1, expstatus, token[0], ctx);
2203     mpd_free(calc);
2204 
2205     calc = _mpd_to_sci(result2, 1);
2206     compare_expected(calc, expected2, expstatus, token[0], ctx);
2207     mpd_free(calc);
2208 
2209     check_equalmem(tmp, op, token[0]);
2210 
2211 
2212     /* result1 == tmp */
2213     mpd_init_rand(tmp);
2214     mpd_copy(tmp, op, ctx);
2215     mpd_init_rand(result2);
2216     ctx->status = 0;
2217 
2218     func(tmp, result2, tmp, tmp, ctx);
2219 
2220     calc = _mpd_to_sci(tmp, 1);
2221     compare_expected(calc, expected1, expstatus, token[0], ctx);
2222     mpd_free(calc);
2223 
2224     calc = _mpd_to_sci(result2, 1);
2225     compare_expected(calc, expected2, expstatus, token[0], ctx);
2226     mpd_free(calc);
2227 
2228     /* Allocation failures */
2229     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
2230         mpd_init_rand(tmp);
2231         mpd_copy(tmp, op, ctx);
2232         mpd_minalloc(result2);
2233         ctx->status = 0;
2234 
2235         mpd_set_alloc_fail(ctx);
2236         func(tmp, result2, tmp, tmp, ctx);
2237         mpd_set_alloc(ctx);
2238 
2239         if (!(ctx->status&MPD_Malloc_error)) {
2240             break;
2241         }
2242         ASSERT(mpd_isnan(tmp))
2243         ASSERT(mpd_isnan(result2))
2244     }
2245     calc = _mpd_to_sci(tmp, 1);
2246     compare_expected(calc, expected1, expstatus, token[0], ctx);
2247     mpd_free(calc);
2248 
2249     calc = _mpd_to_sci(result2, 1);
2250     compare_expected(calc, expected2, expstatus, token[0], ctx);
2251     mpd_free(calc);
2252 
2253 
2254     /* result2 == tmp */
2255     mpd_init_rand(tmp);
2256     mpd_copy(tmp, op, ctx);
2257     mpd_init_rand(result1);
2258     ctx->status = 0;
2259 
2260     func(result1, tmp, tmp, tmp, ctx);
2261 
2262     calc = _mpd_to_sci(result1, 1);
2263     compare_expected(calc, expected1, expstatus, token[0], ctx);
2264     mpd_free(calc);
2265 
2266     calc = _mpd_to_sci(tmp, 1);
2267     compare_expected(calc, expected2, expstatus, token[0], ctx);
2268     mpd_free(calc);
2269 
2270     /* Allocation failures */
2271     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
2272         mpd_init_rand(tmp);
2273         mpd_copy(tmp, op, ctx);
2274         mpd_minalloc(result1);
2275         ctx->status = 0;
2276 
2277         mpd_set_alloc_fail(ctx);
2278         func(result1, tmp, tmp, tmp, ctx);
2279         mpd_set_alloc(ctx);
2280 
2281         if (!(ctx->status&MPD_Malloc_error)) {
2282             break;
2283         }
2284         ASSERT(mpd_isnan(result1))
2285         ASSERT(mpd_isnan(tmp))
2286     }
2287     calc = _mpd_to_sci(result1, 1);
2288     compare_expected(calc, expected1, expstatus, token[0], ctx);
2289     mpd_free(calc);
2290 
2291     calc = _mpd_to_sci(tmp, 1);
2292     compare_expected(calc, expected2, expstatus, token[0], ctx);
2293     mpd_free(calc);
2294 }
2295 
2296 /* Test a ternary function */
2297 static void
_Res_Ternop_Ctx(char * token[],void (* func)(mpd_t *,const mpd_t *,const mpd_t *,const mpd_t *,mpd_context_t *),mpd_context_t * ctx)2298 _Res_Ternop_Ctx(char *token[], void (*func)(mpd_t *, const mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
2299 {
2300     mpd_context_t maxctx;
2301     char *calc;
2302     char *expected;
2303     uint32_t expstatus;
2304     int n, incr;
2305 
2306     mpd_readcontext(&maxctx);
2307     maxctx.traps = MPD_Malloc_error;
2308 
2309     n = scan_3ops_result(op1, op2, op3, &expected, token, &maxctx);
2310     _TripleTest(op1, ctx, token[0]);
2311     _TripleTest(op2, ctx, token[0]);
2312     _TripleTest(op3, ctx, token[0]);
2313 
2314     /* scan expected conditions */
2315     expstatus = scan_conditions(token+n);
2316 
2317 
2318     /* four distinct decimals */
2319     mpd_init_rand(tmp1);
2320     mpd_init_rand(tmp2);
2321     mpd_init_rand(tmp3);
2322     mpd_copy(tmp1, op1, ctx);
2323     mpd_copy(tmp2, op2, ctx);
2324     mpd_copy(tmp3, op3, ctx);
2325     mpd_init_rand(result);
2326     ctx->status = 0;
2327 
2328     mpd_set_alloc_count(ctx);
2329     func(result, tmp1, tmp2, tmp3, ctx);
2330     mpd_set_alloc(ctx);
2331 
2332     calc = _mpd_to_sci(result, 1);
2333     compare_expected(calc, expected, expstatus, token[0], ctx);
2334     mpd_free(calc);
2335     check_equalmem(tmp1, op1, token[0]);
2336     check_equalmem(tmp2, op2, token[0]);
2337     check_equalmem(tmp3, op3, token[0]);
2338 
2339     /* Allocation failures */
2340     incr = 1;
2341     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
2342         mpd_init_rand(tmp1);
2343         mpd_init_rand(tmp2);
2344         mpd_init_rand(tmp3);
2345         mpd_copy(tmp1, op1, ctx);
2346         mpd_copy(tmp2, op2, ctx);
2347         mpd_copy(tmp3, op3, ctx);
2348         mpd_minalloc(result);
2349         ctx->status = 0;
2350 
2351         mpd_set_alloc_fail(ctx);
2352         func(result, tmp1, tmp2, tmp3, ctx);
2353         mpd_set_alloc(ctx);
2354 
2355         if (!(ctx->status&MPD_Malloc_error)) {
2356             break;
2357         }
2358         ASSERT(mpd_isnan(result))
2359 
2360         if (alloc_fail > 100) {
2361             incr = (int)(alloc_count*0.02) + 1;
2362         }
2363     }
2364     calc = _mpd_to_sci(result, 1);
2365     compare_expected(calc, expected, expstatus, token[0], ctx);
2366     mpd_free(calc);
2367     check_equalmem(tmp1, op1, token[0]);
2368     check_equalmem(tmp2, op2, token[0]);
2369     check_equalmem(tmp3, op3, token[0]);
2370 
2371 
2372     /* result == tmp1 */
2373     mpd_init_rand(tmp1);
2374     mpd_init_rand(tmp2);
2375     mpd_init_rand(tmp3);
2376     mpd_copy(tmp1, op1, ctx);
2377     mpd_copy(tmp2, op2, ctx);
2378     mpd_copy(tmp3, op3, ctx);
2379     ctx->status = 0;
2380 
2381     mpd_set_alloc_count(ctx);
2382     func(tmp1, tmp1, tmp2, tmp3, ctx);
2383     mpd_set_alloc(ctx);
2384 
2385     calc = _mpd_to_sci(tmp1, 1);
2386     compare_expected(calc, expected, expstatus, token[0], ctx);
2387     mpd_free(calc);
2388     check_equalmem(tmp2, op2, token[0]);
2389     check_equalmem(tmp3, op3, token[0]);
2390 
2391     /* Allocation failures */
2392     incr = 1;
2393     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
2394         mpd_init_rand(tmp1);
2395         mpd_init_rand(tmp2);
2396         mpd_init_rand(tmp3);
2397         mpd_copy(tmp1, op1, ctx);
2398         mpd_copy(tmp2, op2, ctx);
2399         mpd_copy(tmp3, op3, ctx);
2400         ctx->status = 0;
2401 
2402         mpd_set_alloc_fail(ctx);
2403         func(tmp1, tmp1, tmp2, tmp3, ctx);
2404         mpd_set_alloc(ctx);
2405 
2406         if (!(ctx->status&MPD_Malloc_error)) {
2407             break;
2408         }
2409         ASSERT(mpd_isnan(tmp1))
2410 
2411         if (alloc_fail > 100) {
2412             incr = (int)(alloc_count*0.02) + 1;
2413         }
2414     }
2415     calc = _mpd_to_sci(tmp1, 1);
2416     compare_expected(calc, expected, expstatus, token[0], ctx);
2417     mpd_free(calc);
2418     check_equalmem(tmp2, op2, token[0]);
2419     check_equalmem(tmp3, op3, token[0]);
2420 
2421 
2422     /* result == tmp2 */
2423     mpd_init_rand(tmp1);
2424     mpd_init_rand(tmp2);
2425     mpd_init_rand(tmp3);
2426     mpd_copy(tmp1, op1, ctx);
2427     mpd_copy(tmp2, op2, ctx);
2428     mpd_copy(tmp3, op3, ctx);
2429     ctx->status = 0;
2430 
2431     mpd_set_alloc_count(ctx);
2432     func(tmp2, tmp1, tmp2, tmp3, ctx);
2433     mpd_set_alloc(ctx);
2434 
2435     calc = _mpd_to_sci(tmp2, 1);
2436     compare_expected(calc, expected, expstatus, token[0], ctx);
2437     mpd_free(calc);
2438     check_equalmem(tmp1, op1, token[0]);
2439     check_equalmem(tmp3, op3, token[0]);
2440 
2441     /* Allocation failures */
2442     incr = 1;
2443     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
2444         mpd_init_rand(tmp1);
2445         mpd_init_rand(tmp2);
2446         mpd_init_rand(tmp3);
2447         mpd_copy(tmp1, op1, ctx);
2448         mpd_copy(tmp2, op2, ctx);
2449         mpd_copy(tmp3, op3, ctx);
2450         ctx->status = 0;
2451 
2452         mpd_set_alloc_fail(ctx);
2453         func(tmp2, tmp1, tmp2, tmp3, ctx);
2454         mpd_set_alloc(ctx);
2455 
2456         if (!(ctx->status&MPD_Malloc_error)) {
2457             break;
2458         }
2459         ASSERT(mpd_isnan(tmp2))
2460 
2461         if (alloc_fail > 100) {
2462             incr = (int)(alloc_count*0.02) + 1;
2463         }
2464     }
2465     calc = _mpd_to_sci(tmp2, 1);
2466     compare_expected(calc, expected, expstatus, token[0], ctx);
2467     mpd_free(calc);
2468     check_equalmem(tmp1, op1, token[0]);
2469     check_equalmem(tmp3, op3, token[0]);
2470 
2471 
2472     /* result == tmp3 */
2473     mpd_init_rand(tmp1);
2474     mpd_init_rand(tmp2);
2475     mpd_init_rand(tmp3);
2476     mpd_copy(tmp1, op1, ctx);
2477     mpd_copy(tmp2, op2, ctx);
2478     mpd_copy(tmp3, op3, ctx);
2479     ctx->status = 0;
2480 
2481     mpd_set_alloc_count(ctx);
2482     func(tmp3, tmp1, tmp2, tmp3, ctx);
2483     mpd_set_alloc(ctx);
2484 
2485     calc = _mpd_to_sci(tmp3, 1);
2486     compare_expected(calc, expected, expstatus, token[0], ctx);
2487     mpd_free(calc);
2488     check_equalmem(tmp1, op1, token[0]);
2489     check_equalmem(tmp2, op2, token[0]);
2490 
2491     /* Allocation failures */
2492     incr = 1;
2493     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail += incr) {
2494         mpd_init_rand(tmp1);
2495         mpd_init_rand(tmp2);
2496         mpd_init_rand(tmp3);
2497         mpd_copy(tmp1, op1, ctx);
2498         mpd_copy(tmp2, op2, ctx);
2499         mpd_copy(tmp3, op3, ctx);
2500         ctx->status = 0;
2501 
2502         mpd_set_alloc_fail(ctx);
2503         func(tmp3, tmp1, tmp2, tmp3, ctx);
2504         mpd_set_alloc(ctx);
2505 
2506         if (!(ctx->status&MPD_Malloc_error)) {
2507             break;
2508         }
2509         ASSERT(mpd_isnan(tmp3))
2510 
2511         if (alloc_fail > 100) {
2512             incr = (int)(alloc_count*0.02) + 1;
2513         }
2514     }
2515     calc = _mpd_to_sci(tmp3, 1);
2516     compare_expected(calc, expected, expstatus, token[0], ctx);
2517     mpd_free(calc);
2518     check_equalmem(tmp1, op1, token[0]);
2519     check_equalmem(tmp2, op2, token[0]);
2520 }
2521 
2522 /* Test a ternary function, first and second operand equal */
2523 static void
_Res_EqEqOp_Ctx(char * token[],void (* func)(mpd_t *,const mpd_t *,const mpd_t *,const mpd_t *,mpd_context_t *),mpd_context_t * ctx)2524 _Res_EqEqOp_Ctx(char *token[], void (*func)(mpd_t *, const mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
2525 {
2526     mpd_context_t maxctx;
2527     char *calc;
2528     char *expected;
2529     uint32_t expstatus;
2530     int n;
2531 
2532     mpd_readcontext(&maxctx);
2533     maxctx.traps = MPD_Malloc_error;
2534 
2535     n = scan_2ops_result(op1, op2, &expected, token, &maxctx);
2536     _TripleTest(op1, ctx, token[0]);
2537     _TripleTest(op2, ctx, token[0]);
2538 
2539     /* scan expected conditions */
2540     expstatus = scan_conditions(token+n);
2541 
2542 
2543     /* distinct result */
2544     mpd_init_rand(tmp1);
2545     mpd_init_rand(tmp2);
2546     mpd_copy(tmp1, op1, ctx);
2547     mpd_copy(tmp2, op2, ctx);
2548     mpd_init_rand(result);
2549     ctx->status = 0;
2550 
2551     func(result, tmp1, tmp1, tmp2, ctx);
2552 
2553     calc = _mpd_to_sci(result, 1);
2554     compare_expected(calc, expected, expstatus, token[0], ctx);
2555     mpd_free(calc);
2556     check_equalmem(tmp1, op1, token[0]);
2557     check_equalmem(tmp2, op2, token[0]);
2558 
2559     /* Allocation failures */
2560     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
2561         mpd_init_rand(tmp1);
2562         mpd_init_rand(tmp2);
2563         mpd_copy(tmp1, op1, ctx);
2564         mpd_copy(tmp2, op2, ctx);
2565         mpd_minalloc(result);
2566         ctx->status = 0;
2567 
2568         mpd_set_alloc_fail(ctx);
2569         func(result, tmp1, tmp1, tmp2, ctx);
2570         mpd_set_alloc(ctx);
2571 
2572         if (!(ctx->status&MPD_Malloc_error)) {
2573             break;
2574         }
2575         ASSERT(mpd_isnan(result))
2576     }
2577     calc = _mpd_to_sci(result, 1);
2578     compare_expected(calc, expected, expstatus, token[0], ctx);
2579     mpd_free(calc);
2580     check_equalmem(tmp1, op1, token[0]);
2581     check_equalmem(tmp2, op2, token[0]);
2582 
2583 
2584     /* result == tmp1 */
2585     mpd_init_rand(tmp1);
2586     mpd_init_rand(tmp2);
2587     mpd_copy(tmp1, op1, ctx);
2588     mpd_copy(tmp2, op2, ctx);
2589     ctx->status = 0;
2590 
2591     func(tmp1, tmp1, tmp1, tmp2, ctx);
2592 
2593     calc = _mpd_to_sci(tmp1, 1);
2594     compare_expected(calc, expected, expstatus, token[0], ctx);
2595     mpd_free(calc);
2596     check_equalmem(tmp2, op2, token[0]);
2597 
2598     /* Allocation failures */
2599     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
2600         mpd_init_rand(tmp1);
2601         mpd_init_rand(tmp2);
2602         mpd_copy(tmp1, op1, ctx);
2603         mpd_copy(tmp2, op2, ctx);
2604         ctx->status = 0;
2605 
2606         mpd_set_alloc_fail(ctx);
2607         func(tmp1, tmp1, tmp1, tmp2, ctx);
2608         mpd_set_alloc(ctx);
2609 
2610         if (!(ctx->status&MPD_Malloc_error)) {
2611             break;
2612         }
2613         ASSERT(mpd_isnan(tmp1))
2614     }
2615     calc = _mpd_to_sci(tmp1, 1);
2616     compare_expected(calc, expected, expstatus, token[0], ctx);
2617     mpd_free(calc);
2618     check_equalmem(tmp2, op2, token[0]);
2619 
2620 
2621     /* result == tmp2 */
2622     mpd_init_rand(tmp1);
2623     mpd_init_rand(tmp2);
2624     mpd_copy(tmp1, op1, ctx);
2625     mpd_copy(tmp2, op2, ctx);
2626     ctx->status = 0;
2627 
2628     func(tmp2, tmp1, tmp1, tmp2, ctx);
2629 
2630     calc = _mpd_to_sci(tmp2, 1);
2631     compare_expected(calc, expected, expstatus, token[0], ctx);
2632     mpd_free(calc);
2633     check_equalmem(tmp1, op1, token[0]);
2634 
2635     /* Allocation failures */
2636     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
2637         mpd_init_rand(tmp1);
2638         mpd_init_rand(tmp2);
2639         mpd_copy(tmp1, op1, ctx);
2640         mpd_copy(tmp2, op2, ctx);
2641         ctx->status = 0;
2642 
2643         mpd_set_alloc_fail(ctx);
2644         func(tmp2, tmp1, tmp1, tmp2, ctx);
2645         mpd_set_alloc(ctx);
2646 
2647         if (!(ctx->status&MPD_Malloc_error)) {
2648             break;
2649         }
2650         ASSERT(mpd_isnan(tmp2))
2651     }
2652     calc = _mpd_to_sci(tmp2, 1);
2653     compare_expected(calc, expected, expstatus, token[0], ctx);
2654     mpd_free(calc);
2655     check_equalmem(tmp1, op1, token[0]);
2656 }
2657 
2658 /* Test a ternary function, first and third operand equal */
2659 static void
_Res_EqOpEq_Ctx(char * token[],void (* func)(mpd_t *,const mpd_t *,const mpd_t *,const mpd_t *,mpd_context_t *),mpd_context_t * ctx)2660 _Res_EqOpEq_Ctx(char *token[], void (*func)(mpd_t *, const mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
2661 {
2662     mpd_context_t maxctx;
2663     char *calc;
2664     char *expected;
2665     uint32_t expstatus;
2666     int n;
2667 
2668     mpd_readcontext(&maxctx);
2669     maxctx.traps = MPD_Malloc_error;
2670 
2671     n = scan_2ops_result(op1, op2, &expected, token, &maxctx);
2672     _TripleTest(op1, ctx, token[0]);
2673     _TripleTest(op2, ctx, token[0]);
2674 
2675     /* scan expected conditions */
2676     expstatus = scan_conditions(token+n);
2677 
2678 
2679     /* distinct result */
2680     mpd_init_rand(tmp1);
2681     mpd_init_rand(tmp2);
2682     mpd_copy(tmp1, op1, ctx);
2683     mpd_copy(tmp2, op2, ctx);
2684     mpd_init_rand(result);
2685     ctx->status = 0;
2686 
2687     func(result, tmp1, tmp2, tmp1, ctx);
2688 
2689     calc = _mpd_to_sci(result, 1);
2690     compare_expected(calc, expected, expstatus, token[0], ctx);
2691     mpd_free(calc);
2692     check_equalmem(tmp1, op1, token[0]);
2693     check_equalmem(tmp2, op2, token[0]);
2694 
2695     /* Allocation failures */
2696     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
2697         mpd_init_rand(tmp1);
2698         mpd_init_rand(tmp2);
2699         mpd_copy(tmp1, op1, ctx);
2700         mpd_copy(tmp2, op2, ctx);
2701         mpd_minalloc(result);
2702         ctx->status = 0;
2703 
2704         mpd_set_alloc_fail(ctx);
2705         func(result, tmp1, tmp2, tmp1, ctx);
2706         mpd_set_alloc(ctx);
2707 
2708         if (!(ctx->status&MPD_Malloc_error)) {
2709             break;
2710         }
2711         ASSERT(mpd_isnan(result))
2712     }
2713     calc = _mpd_to_sci(result, 1);
2714     compare_expected(calc, expected, expstatus, token[0], ctx);
2715     mpd_free(calc);
2716     check_equalmem(tmp1, op1, token[0]);
2717     check_equalmem(tmp2, op2, token[0]);
2718 
2719 
2720     /* result == tmp1 */
2721     mpd_init_rand(tmp1);
2722     mpd_init_rand(tmp2);
2723     mpd_copy(tmp1, op1, ctx);
2724     mpd_copy(tmp2, op2, ctx);
2725     ctx->status = 0;
2726 
2727     func(tmp1, tmp1, tmp2, tmp1, ctx);
2728 
2729     calc = _mpd_to_sci(tmp1, 1);
2730     compare_expected(calc, expected, expstatus, token[0], ctx);
2731     mpd_free(calc);
2732     check_equalmem(tmp2, op2, token[0]);
2733 
2734     /* Allocation failures */
2735     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
2736         mpd_init_rand(tmp1);
2737         mpd_init_rand(tmp2);
2738         mpd_copy(tmp1, op1, ctx);
2739         mpd_copy(tmp2, op2, ctx);
2740         ctx->status = 0;
2741 
2742         mpd_set_alloc_fail(ctx);
2743         func(tmp1, tmp1, tmp2, tmp1, ctx);
2744         mpd_set_alloc(ctx);
2745 
2746         if (!(ctx->status&MPD_Malloc_error)) {
2747             break;
2748         }
2749         ASSERT(mpd_isnan(tmp1))
2750     }
2751     calc = _mpd_to_sci(tmp1, 1);
2752     compare_expected(calc, expected, expstatus, token[0], ctx);
2753     mpd_free(calc);
2754     check_equalmem(tmp2, op2, token[0]);
2755 
2756 
2757     /* result == tmp2 */
2758     mpd_init_rand(tmp1);
2759     mpd_init_rand(tmp2);
2760     mpd_copy(tmp1, op1, ctx);
2761     mpd_copy(tmp2, op2, ctx);
2762     ctx->status = 0;
2763 
2764     func(tmp2, tmp1, tmp2, tmp1, ctx);
2765 
2766     calc = _mpd_to_sci(tmp2, 1);
2767     compare_expected(calc, expected, expstatus, token[0], ctx);
2768     mpd_free(calc);
2769     check_equalmem(tmp1, op1, token[0]);
2770 
2771     /* Allocation failures */
2772     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
2773         mpd_init_rand(tmp1);
2774         mpd_init_rand(tmp2);
2775         mpd_copy(tmp1, op1, ctx);
2776         mpd_copy(tmp2, op2, ctx);
2777         ctx->status = 0;
2778 
2779         mpd_set_alloc_fail(ctx);
2780         func(tmp2, tmp1, tmp2, tmp1, ctx);
2781         mpd_set_alloc(ctx);
2782 
2783         if (!(ctx->status&MPD_Malloc_error)) {
2784             break;
2785         }
2786         ASSERT(mpd_isnan(tmp2))
2787     }
2788     calc = _mpd_to_sci(tmp2, 1);
2789     compare_expected(calc, expected, expstatus, token[0], ctx);
2790     mpd_free(calc);
2791     check_equalmem(tmp1, op1, token[0]);
2792 }
2793 
2794 /* Test a ternary function, second and third operand equal */
2795 static void
_Res_OpEqEq_Ctx(char * token[],void (* func)(mpd_t *,const mpd_t *,const mpd_t *,const mpd_t *,mpd_context_t *),mpd_context_t * ctx)2796 _Res_OpEqEq_Ctx(char *token[], void (*func)(mpd_t *, const mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
2797 {
2798     mpd_context_t maxctx;
2799     char *calc;
2800     char *expected;
2801     uint32_t expstatus;
2802     int n;
2803 
2804     mpd_readcontext(&maxctx);
2805     maxctx.traps = MPD_Malloc_error;
2806 
2807     n = scan_2ops_result(op1, op2, &expected, token, &maxctx);
2808     _TripleTest(op1, ctx, token[0]);
2809     _TripleTest(op2, ctx, token[0]);
2810 
2811     /* scan expected conditions */
2812     expstatus = scan_conditions(token+n);
2813 
2814 
2815     /* distinct result */
2816     mpd_init_rand(tmp1);
2817     mpd_init_rand(tmp2);
2818     mpd_copy(tmp1, op1, ctx);
2819     mpd_copy(tmp2, op2, ctx);
2820     mpd_init_rand(result);
2821     ctx->status = 0;
2822 
2823     func(result, tmp1, tmp2, tmp2, ctx);
2824 
2825     calc = _mpd_to_sci(result, 1);
2826     compare_expected(calc, expected, expstatus, token[0], ctx);
2827     mpd_free(calc);
2828     check_equalmem(tmp1, op1, token[0]);
2829     check_equalmem(tmp2, op2, token[0]);
2830 
2831     /* Allocation failures */
2832     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
2833         mpd_init_rand(tmp1);
2834         mpd_init_rand(tmp2);
2835         mpd_copy(tmp1, op1, ctx);
2836         mpd_copy(tmp2, op2, ctx);
2837         mpd_minalloc(result);
2838         ctx->status = 0;
2839 
2840         mpd_set_alloc_fail(ctx);
2841         func(result, tmp1, tmp2, tmp2, ctx);
2842         mpd_set_alloc(ctx);
2843 
2844         if (!(ctx->status&MPD_Malloc_error)) {
2845             break;
2846         }
2847         ASSERT(mpd_isnan(result))
2848     }
2849     calc = _mpd_to_sci(result, 1);
2850     compare_expected(calc, expected, expstatus, token[0], ctx);
2851     mpd_free(calc);
2852     check_equalmem(tmp1, op1, token[0]);
2853     check_equalmem(tmp2, op2, token[0]);
2854 
2855 
2856     /* result == tmp2 */
2857     mpd_init_rand(tmp1);
2858     mpd_init_rand(tmp2);
2859     mpd_copy(tmp1, op1, ctx);
2860     mpd_copy(tmp2, op2, ctx);
2861     ctx->status = 0;
2862 
2863     func(tmp2, tmp1, tmp2, tmp2, ctx);
2864 
2865     calc = _mpd_to_sci(tmp2, 1);
2866     compare_expected(calc, expected, expstatus, token[0], ctx);
2867     mpd_free(calc);
2868     check_equalmem(tmp1, op1, token[0]);
2869 
2870     /* Allocation failures */
2871     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
2872         mpd_init_rand(tmp1);
2873         mpd_init_rand(tmp2);
2874         mpd_copy(tmp1, op1, ctx);
2875         mpd_copy(tmp2, op2, ctx);
2876         ctx->status = 0;
2877 
2878         mpd_set_alloc_fail(ctx);
2879         func(tmp2, tmp1, tmp2, tmp2, ctx);
2880         mpd_set_alloc(ctx);
2881 
2882         if (!(ctx->status&MPD_Malloc_error)) {
2883             break;
2884         }
2885         ASSERT(mpd_isnan(tmp2))
2886     }
2887     calc = _mpd_to_sci(tmp2, 1);
2888     compare_expected(calc, expected, expstatus, token[0], ctx);
2889     mpd_free(calc);
2890     check_equalmem(tmp1, op1, token[0]);
2891 
2892 
2893     /* result == tmp1 */
2894     mpd_init_rand(tmp1);
2895     mpd_init_rand(tmp2);
2896     mpd_copy(tmp1, op1, ctx);
2897     mpd_copy(tmp2, op2, ctx);
2898     ctx->status = 0;
2899 
2900     func(tmp1, tmp1, tmp2, tmp2, ctx);
2901 
2902     calc = _mpd_to_sci(tmp1, 1);
2903     compare_expected(calc, expected, expstatus, token[0], ctx);
2904     mpd_free(calc);
2905     check_equalmem(tmp2, op2, token[0]);
2906 
2907     /* Allocation failures */
2908     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
2909         mpd_init_rand(tmp1);
2910         mpd_init_rand(tmp2);
2911         mpd_copy(tmp1, op1, ctx);
2912         mpd_copy(tmp2, op2, ctx);
2913         ctx->status = 0;
2914 
2915         mpd_set_alloc_fail(ctx);
2916         func(tmp1, tmp1, tmp2, tmp2, ctx);
2917         mpd_set_alloc(ctx);
2918 
2919         if (!(ctx->status&MPD_Malloc_error)) {
2920             break;
2921         }
2922         ASSERT(mpd_isnan(tmp1))
2923     }
2924     calc = _mpd_to_sci(tmp1, 1);
2925     compare_expected(calc, expected, expstatus, token[0], ctx);
2926     mpd_free(calc);
2927     check_equalmem(tmp2, op2, token[0]);
2928 }
2929 
2930 /* Test a ternary function, first, second and third operand equal */
2931 static void
_Res_EqEqEq_Ctx(char * token[],void (* func)(mpd_t *,const mpd_t *,const mpd_t *,const mpd_t *,mpd_context_t *),mpd_context_t * ctx)2932 _Res_EqEqEq_Ctx(char *token[], void (*func)(mpd_t *, const mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
2933 {
2934     mpd_context_t maxctx;
2935     char *calc;
2936     char *expected;
2937     uint32_t expstatus;
2938     int n;
2939 
2940     mpd_readcontext(&maxctx);
2941     maxctx.traps = MPD_Malloc_error;
2942 
2943     n = scan_1op_result(op, &expected, token, &maxctx);
2944     _TripleTest(op, ctx, token[0]);
2945 
2946     /* scan expected conditions */
2947     expstatus = scan_conditions(token+n);
2948 
2949 
2950     /* distinct result */
2951     mpd_init_rand(tmp);
2952     mpd_copy(tmp, op, ctx);
2953     mpd_init_rand(result);
2954     ctx->status = 0;
2955 
2956     func(result, tmp, tmp, tmp, ctx);
2957 
2958     calc = _mpd_to_sci(result, 1);
2959     compare_expected(calc, expected, expstatus, token[0], ctx);
2960     mpd_free(calc);
2961     check_equalmem(tmp, op, token[0]);
2962 
2963     /* Allocation failures */
2964     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
2965         mpd_init_rand(tmp);
2966         mpd_copy(tmp, op, ctx);
2967         mpd_minalloc(result);
2968         ctx->status = 0;
2969 
2970         mpd_set_alloc_fail(ctx);
2971         func(result, tmp, tmp, tmp, ctx);
2972         mpd_set_alloc(ctx);
2973 
2974         if (!(ctx->status&MPD_Malloc_error)) {
2975             break;
2976         }
2977         ASSERT(mpd_isnan(result))
2978     }
2979     calc = _mpd_to_sci(result, 1);
2980     compare_expected(calc, expected, expstatus, token[0], ctx);
2981     mpd_free(calc);
2982     check_equalmem(tmp, op, token[0]);
2983 
2984 
2985     /* result == tmp */
2986     mpd_init_rand(tmp);
2987     mpd_copy(tmp, op, ctx);
2988     ctx->status = 0;
2989 
2990     func(tmp, tmp, tmp, tmp, ctx);
2991 
2992     calc = _mpd_to_sci(tmp, 1);
2993     compare_expected(calc, expected, expstatus, token[0], ctx);
2994     mpd_free(calc);
2995 
2996     /* Allocation failures */
2997     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
2998         mpd_init_rand(tmp);
2999         mpd_copy(tmp, op, ctx);
3000         ctx->status = 0;
3001 
3002         mpd_set_alloc_fail(ctx);
3003         func(tmp, tmp, tmp, tmp, ctx);
3004         mpd_set_alloc(ctx);
3005 
3006         if (!(ctx->status&MPD_Malloc_error)) {
3007             break;
3008         }
3009         ASSERT(mpd_isnan(tmp))
3010     }
3011     calc = _mpd_to_sci(tmp, 1);
3012     compare_expected(calc, expected, expstatus, token[0], ctx);
3013     mpd_free(calc);
3014 }
3015 
3016 /*
3017  * Test a binary function that returns an additional integer result.
3018  * Used for the comparison functions.
3019  */
3020 static void
_Int_Res_Binop_Ctx(char * token[],int (* func)(mpd_t *,const mpd_t *,const mpd_t *,mpd_context_t *),mpd_context_t * ctx)3021 _Int_Res_Binop_Ctx(char *token[], int (*func)(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
3022 {
3023     mpd_context_t maxctx;
3024     char *calc;
3025     char *expected;
3026     int int_result;
3027     char buf[11];
3028     uint32_t expstatus;
3029     int n;
3030 
3031     mpd_readcontext(&maxctx);
3032     maxctx.traps = MPD_Malloc_error;
3033 
3034     n = scan_2ops_result(op1, op2, &expected, token, &maxctx);
3035     _TripleTest(op1, ctx, token[0]);
3036     _TripleTest(op2, ctx, token[0]);
3037 
3038     /* scan expected conditions */
3039     expstatus = scan_conditions(token+n);
3040 
3041 
3042     /* three distinct decimals */
3043     mpd_init_rand(tmp1);
3044     mpd_init_rand(tmp2);
3045     mpd_copy(tmp1, op1, ctx);
3046     mpd_copy(tmp2, op2, ctx);
3047     mpd_init_rand(result);
3048     ctx->status = 0;
3049 
3050     int_result = func(result, tmp1, tmp2, ctx);
3051 
3052     calc = _mpd_to_sci(result, 1);
3053     compare_expected(calc, expected, expstatus, token[0], ctx);
3054     mpd_free(calc);
3055     snprintf(buf, 11, "%d", int_result);
3056     if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
3057         compare_expected(buf, expected, expstatus, token[0], ctx);
3058     }
3059     check_equalmem(tmp1, op1, token[0]);
3060     check_equalmem(tmp2, op2, token[0]);
3061 
3062     /* Allocation failures */
3063     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
3064         mpd_init_rand(tmp1);
3065         mpd_init_rand(tmp2);
3066         mpd_copy(tmp1, op1, ctx);
3067         mpd_copy(tmp2, op2, ctx);
3068         mpd_minalloc(result);
3069         ctx->status = 0;
3070 
3071         mpd_set_alloc_fail(ctx);
3072         int_result = func(result, tmp1, tmp2, ctx);
3073         mpd_set_alloc(ctx);
3074 
3075         if (!(ctx->status&MPD_Malloc_error)) {
3076             break;
3077         }
3078         ASSERT(mpd_isnan(result))
3079     }
3080     calc = _mpd_to_sci(result, 1);
3081     compare_expected(calc, expected, expstatus, token[0], ctx);
3082     mpd_free(calc);
3083     snprintf(buf, 11, "%d", int_result);
3084     if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
3085         compare_expected(buf, expected, expstatus, token[0], ctx);
3086     }
3087     check_equalmem(tmp1, op1, token[0]);
3088     check_equalmem(tmp2, op2, token[0]);
3089 
3090 
3091     /* result == tmp1 */
3092     mpd_init_rand(tmp1);
3093     mpd_init_rand(tmp2);
3094     mpd_copy(tmp1, op1, ctx);
3095     mpd_copy(tmp2, op2, ctx);
3096     ctx->status = 0;
3097 
3098     int_result = func(tmp1, tmp1, tmp2, ctx);
3099 
3100     calc = _mpd_to_sci(tmp1, 1);
3101     compare_expected(calc, expected, expstatus, token[0], ctx);
3102     mpd_free(calc);
3103     snprintf(buf, 11, "%d", int_result);
3104     if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
3105         compare_expected(buf, expected, expstatus, token[0], ctx);
3106     }
3107     check_equalmem(tmp2, op2, token[0]);
3108 
3109     /* Allocation failures */
3110     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
3111         mpd_init_rand(tmp1);
3112         mpd_init_rand(tmp2);
3113         mpd_copy(tmp1, op1, ctx);
3114         mpd_copy(tmp2, op2, ctx);
3115         ctx->status = 0;
3116 
3117         mpd_set_alloc_fail(ctx);
3118         int_result = func(tmp1, tmp1, tmp2, ctx);
3119         mpd_set_alloc(ctx);
3120 
3121         if (!(ctx->status&MPD_Malloc_error)) {
3122             break;
3123         }
3124         ASSERT(mpd_isnan(tmp1))
3125     }
3126     calc = _mpd_to_sci(tmp1, 1);
3127     compare_expected(calc, expected, expstatus, token[0], ctx);
3128     mpd_free(calc);
3129     snprintf(buf, 11, "%d", int_result);
3130     if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
3131         compare_expected(buf, expected, expstatus, token[0], ctx);
3132     }
3133     check_equalmem(tmp2, op2, token[0]);
3134 
3135 
3136 
3137     /* result == tmp2 */
3138     mpd_init_rand(tmp1);
3139     mpd_init_rand(tmp2);
3140     mpd_copy(tmp1, op1, ctx);
3141     mpd_copy(tmp2, op2, ctx);
3142     ctx->status = 0;
3143 
3144     int_result = func(tmp2, tmp1, tmp2, ctx);
3145 
3146     calc = _mpd_to_sci(tmp2, 1);
3147     compare_expected(calc, expected, expstatus, token[0], ctx);
3148     mpd_free(calc);
3149     snprintf(buf, 11, "%d", int_result);
3150     if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
3151         compare_expected(buf, expected, expstatus, token[0], ctx);
3152     }
3153     check_equalmem(tmp1, op1, token[0]);
3154 
3155     /* Allocation failures */
3156     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
3157         mpd_init_rand(tmp1);
3158         mpd_init_rand(tmp2);
3159         mpd_copy(tmp1, op1, ctx);
3160         mpd_copy(tmp2, op2, ctx);
3161         ctx->status = 0;
3162 
3163         mpd_set_alloc_fail(ctx);
3164         int_result = func(tmp2, tmp1, tmp2, ctx);
3165         mpd_set_alloc(ctx);
3166 
3167         if (!(ctx->status&MPD_Malloc_error)) {
3168             break;
3169         }
3170         ASSERT(mpd_isnan(tmp2))
3171     }
3172     calc = _mpd_to_sci(tmp2, 1);
3173     compare_expected(calc, expected, expstatus, token[0], ctx);
3174     mpd_free(calc);
3175     snprintf(buf, 11, "%d", int_result);
3176     if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
3177         compare_expected(buf, expected, expstatus, token[0], ctx);
3178     }
3179     check_equalmem(tmp1, op1, token[0]);
3180 }
3181 
3182 /*
3183  * Test a binary function that returns an additional integer result.
3184  * Equal operands.
3185  * Used for the comparison functions.
3186  */
3187 static void
_Int_Res_EqualBinop_Ctx(char * token[],int (* func)(mpd_t *,const mpd_t *,const mpd_t *,mpd_context_t *),mpd_context_t * ctx)3188 _Int_Res_EqualBinop_Ctx(char *token[], int (*func)(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
3189 {
3190     mpd_context_t maxctx;
3191     char *calc;
3192     char *expected;
3193     int int_result;
3194     char buf[11];
3195     uint32_t expstatus;
3196     int n;
3197 
3198     mpd_readcontext(&maxctx);
3199     maxctx.traps = MPD_Malloc_error;
3200 
3201     n = scan_1op_result(op, &expected, token, &maxctx);
3202     _TripleTest(op, ctx, token[0]);
3203 
3204     /* scan expected conditions */
3205     expstatus = scan_conditions(token+n);
3206 
3207 
3208     /* equal operands */
3209     mpd_init_rand(tmp);
3210     mpd_copy(tmp, op, ctx);
3211     mpd_init_rand(result);
3212     ctx->status = 0;
3213 
3214     int_result = func(result, tmp, tmp, ctx);
3215 
3216     calc = _mpd_to_sci(result, 1);
3217     compare_expected(calc, expected, expstatus, token[0], ctx);
3218     mpd_free(calc);
3219     snprintf(buf, 11, "%d", int_result);
3220     if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
3221         compare_expected(buf, expected, expstatus, token[0], ctx);
3222     }
3223     check_equalmem(tmp, op, token[0]);
3224 
3225     /* Allocation failures */
3226     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
3227         mpd_init_rand(tmp);
3228         mpd_copy(tmp, op, ctx);
3229         mpd_minalloc(result);
3230         ctx->status = 0;
3231 
3232         mpd_set_alloc_fail(ctx);
3233         int_result = func(result, tmp, tmp, ctx);
3234         mpd_set_alloc(ctx);
3235 
3236         if (!(ctx->status&MPD_Malloc_error)) {
3237             break;
3238         }
3239         ASSERT(mpd_isnan(result))
3240     }
3241     calc = _mpd_to_sci(result, 1);
3242     compare_expected(calc, expected, expstatus, token[0], ctx);
3243     mpd_free(calc);
3244     snprintf(buf, 11, "%d", int_result);
3245     if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
3246         compare_expected(buf, expected, expstatus, token[0], ctx);
3247     }
3248     check_equalmem(tmp, op, token[0]);
3249 
3250 
3251     /* all parameters equal */
3252     mpd_init_rand(tmp);
3253     mpd_copy(tmp, op, ctx);
3254     ctx->status = 0;
3255 
3256     int_result = func(tmp, tmp, tmp, ctx);
3257 
3258     calc = _mpd_to_sci(tmp, 1);
3259     compare_expected(calc, expected, expstatus, token[0], ctx);
3260     mpd_free(calc);
3261     snprintf(buf, 11, "%d", int_result);
3262     if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
3263         compare_expected(buf, expected, expstatus, token[0], ctx);
3264     }
3265 
3266     /* Allocation failures */
3267     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
3268         mpd_init_rand(tmp);
3269         mpd_copy(tmp, op, ctx);
3270         ctx->status = 0;
3271 
3272         mpd_set_alloc_fail(ctx);
3273         int_result = func(tmp, tmp, tmp, ctx);
3274         mpd_set_alloc(ctx);
3275 
3276         if (!(ctx->status&MPD_Malloc_error)) {
3277             break;
3278         }
3279         ASSERT(mpd_isnan(tmp))
3280     }
3281     calc = _mpd_to_sci(tmp, 1);
3282     compare_expected(calc, expected, expstatus, token[0], ctx);
3283     mpd_free(calc);
3284     snprintf(buf, 11, "%d", int_result);
3285     if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
3286         compare_expected(buf, expected, expstatus, token[0], ctx);
3287     }
3288 }
3289 
3290 /*
3291  * Test a binary function that returns an additional integer result.
3292  * Function does not take a context argument.
3293  * Used for the comparison functions.
3294  */
3295 static void
_Int_Res_Binop(char * token[],int (* func)(mpd_t *,const mpd_t *,const mpd_t *),mpd_context_t * ctx)3296 _Int_Res_Binop(char *token[], int (*func)(mpd_t *, const mpd_t *, const mpd_t *), mpd_context_t *ctx)
3297 {
3298     mpd_context_t maxctx;
3299     char *calc;
3300     char *expected;
3301     int int_result;
3302     char buf[11];
3303     uint32_t expstatus;
3304     int n;
3305 
3306     mpd_readcontext(&maxctx);
3307     maxctx.traps = MPD_Malloc_error;
3308 
3309     n = scan_2ops_result(op1, op2, &expected, token, &maxctx);
3310     _TripleTest(op1, ctx, token[0]);
3311     _TripleTest(op2, ctx, token[0]);
3312 
3313     /* scan expected conditions */
3314     expstatus = scan_conditions(token+n);
3315 
3316 
3317     /* three distinct decimals */
3318     mpd_init_rand(tmp1);
3319     mpd_init_rand(tmp2);
3320     mpd_copy(tmp1, op1, ctx);
3321     mpd_copy(tmp2, op2, ctx);
3322     mpd_init_rand(result);
3323     ctx->status = 0;
3324 
3325     int_result = func(result, tmp1, tmp2);
3326 
3327     calc = _mpd_to_sci(result, 1);
3328     compare_expected(calc, expected, expstatus, token[0], ctx);
3329     mpd_free(calc);
3330     snprintf(buf, 11, "%d", int_result);
3331     if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
3332         compare_expected(buf, expected, expstatus, token[0], ctx);
3333     }
3334     check_equalmem(tmp1, op1, token[0]);
3335     check_equalmem(tmp2, op2, token[0]);
3336 
3337     /* Allocation failures */
3338     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
3339         mpd_init_rand(tmp1);
3340         mpd_init_rand(tmp2);
3341         mpd_copy(tmp1, op1, ctx);
3342         mpd_copy(tmp2, op2, ctx);
3343         mpd_minalloc(result);
3344         ctx->status = 0;
3345 
3346         mpd_set_alloc_fail(ctx);
3347         int_result = func(result, tmp1, tmp2);
3348         mpd_set_alloc(ctx);
3349 
3350         if (!(ctx->status&MPD_Malloc_error)) {
3351             break;
3352         }
3353         ASSERT(mpd_isnan(result))
3354     }
3355     calc = _mpd_to_sci(result, 1);
3356     compare_expected(calc, expected, expstatus, token[0], ctx);
3357     mpd_free(calc);
3358     snprintf(buf, 11, "%d", int_result);
3359     if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
3360         compare_expected(buf, expected, expstatus, token[0], ctx);
3361     }
3362     check_equalmem(tmp1, op1, token[0]);
3363     check_equalmem(tmp2, op2, token[0]);
3364 
3365 
3366     /* result == tmp1 */
3367     mpd_init_rand(tmp1);
3368     mpd_init_rand(tmp2);
3369     mpd_copy(tmp1, op1, ctx);
3370     mpd_copy(tmp2, op2, ctx);
3371     ctx->status = 0;
3372 
3373     int_result = func(tmp1, tmp1, tmp2);
3374 
3375     calc = _mpd_to_sci(tmp1, 1);
3376     compare_expected(calc, expected, expstatus, token[0], ctx);
3377     mpd_free(calc);
3378     snprintf(buf, 11, "%d", int_result);
3379     if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
3380         compare_expected(buf, expected, expstatus, token[0], ctx);
3381     }
3382     check_equalmem(tmp2, op2, token[0]);
3383 
3384     /* Allocation failures */
3385     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
3386         mpd_init_rand(tmp1);
3387         mpd_init_rand(tmp2);
3388         mpd_copy(tmp1, op1, ctx);
3389         mpd_copy(tmp2, op2, ctx);
3390         ctx->status = 0;
3391 
3392         mpd_set_alloc_fail(ctx);
3393         int_result = func(tmp1, tmp1, tmp2);
3394         mpd_set_alloc(ctx);
3395 
3396         if (!(ctx->status&MPD_Malloc_error)) {
3397             break;
3398         }
3399         ASSERT(mpd_isnan(tmp1))
3400     }
3401     calc = _mpd_to_sci(tmp1, 1);
3402     compare_expected(calc, expected, expstatus, token[0], ctx);
3403     mpd_free(calc);
3404     snprintf(buf, 11, "%d", int_result);
3405     if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
3406         compare_expected(buf, expected, expstatus, token[0], ctx);
3407     }
3408     check_equalmem(tmp2, op2, token[0]);
3409 
3410 
3411     /* result == tmp2 */
3412     mpd_init_rand(tmp1);
3413     mpd_init_rand(tmp2);
3414     mpd_copy(tmp1, op1, ctx);
3415     mpd_copy(tmp2, op2, ctx);
3416     ctx->status = 0;
3417 
3418     int_result = func(tmp2, tmp1, tmp2);
3419 
3420     calc = _mpd_to_sci(tmp2, 1);
3421     compare_expected(calc, expected, expstatus, token[0], ctx);
3422     mpd_free(calc);
3423     snprintf(buf, 11, "%d", int_result);
3424     if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
3425         compare_expected(buf, expected, expstatus, token[0], ctx);
3426     }
3427     check_equalmem(tmp1, op1, token[0]);
3428 
3429     /* Allocation failures */
3430     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
3431         mpd_init_rand(tmp1);
3432         mpd_init_rand(tmp2);
3433         mpd_copy(tmp1, op1, ctx);
3434         mpd_copy(tmp2, op2, ctx);
3435         ctx->status = 0;
3436 
3437         mpd_set_alloc_fail(ctx);
3438         int_result = func(tmp2, tmp1, tmp2);
3439         mpd_set_alloc(ctx);
3440 
3441         if (!(ctx->status&MPD_Malloc_error)) {
3442             break;
3443         }
3444         ASSERT(mpd_isnan(tmp2))
3445     }
3446     calc = _mpd_to_sci(tmp2, 1);
3447     compare_expected(calc, expected, expstatus, token[0], ctx);
3448     mpd_free(calc);
3449     snprintf(buf, 11, "%d", int_result);
3450     if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
3451         compare_expected(buf, expected, expstatus, token[0], ctx);
3452     }
3453     check_equalmem(tmp1, op1, token[0]);
3454 }
3455 
3456 /*
3457  * Test a binary function that returns an additional integer result.
3458  * Function does not take a context argument.
3459  * Equal operands.
3460  * Used for the comparison functions.
3461  */
3462 static void
_Int_Res_EqualBinop(char * token[],int (* func)(mpd_t *,const mpd_t *,const mpd_t *),mpd_context_t * ctx)3463 _Int_Res_EqualBinop(char *token[], int (*func)(mpd_t *, const mpd_t *, const mpd_t *), mpd_context_t *ctx)
3464 {
3465     mpd_context_t maxctx;
3466     char *calc;
3467     char *expected;
3468     int int_result;
3469     char buf[11];
3470     uint32_t expstatus;
3471     int n;
3472 
3473     mpd_readcontext(&maxctx);
3474     maxctx.traps = MPD_Malloc_error;
3475 
3476     n = scan_1op_result(op, &expected, token, &maxctx);
3477     _TripleTest(op, ctx, token[0]);
3478 
3479     /* scan expected conditions */
3480     expstatus = scan_conditions(token+n);
3481 
3482 
3483     /* equal operands */
3484     mpd_init_rand(tmp);
3485     mpd_copy(tmp, op, ctx);
3486     mpd_init_rand(result);
3487     ctx->status = 0;
3488 
3489     int_result = func(result, tmp, tmp);
3490 
3491     calc = _mpd_to_sci(result, 1);
3492     compare_expected(calc, expected, expstatus, token[0], ctx);
3493     mpd_free(calc);
3494     snprintf(buf, 11, "%d", int_result);
3495     if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
3496         compare_expected(buf, expected, expstatus, token[0], ctx);
3497     }
3498     check_equalmem(tmp, op, token[0]);
3499 
3500     /* Allocation failures */
3501     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
3502         mpd_init_rand(tmp);
3503         mpd_copy(tmp, op, ctx);
3504         mpd_minalloc(result);
3505         ctx->status = 0;
3506 
3507         mpd_set_alloc_fail(ctx);
3508         int_result = func(result, tmp, tmp);
3509         mpd_set_alloc(ctx);
3510 
3511         if (!(ctx->status&MPD_Malloc_error)) {
3512             break;
3513         }
3514         ASSERT(mpd_isnan(result))
3515     }
3516     calc = _mpd_to_sci(result, 1);
3517     compare_expected(calc, expected, expstatus, token[0], ctx);
3518     mpd_free(calc);
3519     snprintf(buf, 11, "%d", int_result);
3520     if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
3521         compare_expected(buf, expected, expstatus, token[0], ctx);
3522     }
3523     check_equalmem(tmp, op, token[0]);
3524 
3525 
3526     /* all parameters equal */
3527     mpd_init_rand(tmp);
3528     mpd_copy(tmp, op, ctx);
3529     ctx->status = 0;
3530 
3531     int_result = func(tmp, tmp, tmp);
3532 
3533     calc = _mpd_to_sci(tmp, 1);
3534     compare_expected(calc, expected, expstatus, token[0], ctx);
3535     mpd_free(calc);
3536     snprintf(buf, 11, "%d", int_result);
3537     if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
3538         compare_expected(buf, expected, expstatus, token[0], ctx);
3539     }
3540 
3541     /* Allocation failures */
3542     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
3543         mpd_init_rand(tmp);
3544         mpd_copy(tmp, op, ctx);
3545         ctx->status = 0;
3546 
3547         mpd_set_alloc_fail(ctx);
3548         int_result = func(tmp, tmp, tmp);
3549         mpd_set_alloc(ctx);
3550 
3551         if (!(ctx->status&MPD_Malloc_error)) {
3552             break;
3553         }
3554         ASSERT(mpd_isnan(tmp))
3555     }
3556     calc = _mpd_to_sci(tmp, 1);
3557     compare_expected(calc, expected, expstatus, token[0], ctx);
3558     mpd_free(calc);
3559     snprintf(buf, 11, "%d", int_result);
3560     if (int_result != INT_MAX) { /* NaN cases are skipped for the int_retval */
3561         compare_expected(buf, expected, expstatus, token[0], ctx);
3562     }
3563 }
3564 
3565 /*
3566  * Test a binary function that returns only an integer result.
3567  * Used for the cmp functions.
3568  */
3569 enum {SKIP_NONE, SKIP_NAN, SKIP_NONINT};
3570 static void
_Int_Binop_Ctx(int skip,char * token[],int (* func)(const mpd_t *,const mpd_t *,mpd_context_t *),mpd_context_t * ctx)3571 _Int_Binop_Ctx(int skip, char *token[], int (*func)(const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
3572 {
3573     mpd_context_t maxctx;
3574     int int_result;
3575     char buf[11];
3576     char *expected;
3577     uint32_t expstatus;
3578     int n;
3579 
3580     mpd_readcontext(&maxctx);
3581     maxctx.traps = MPD_Malloc_error;
3582 
3583     n = scan_2ops_result(op1, op2, &expected, token, &maxctx);
3584     _TripleTest(op1, ctx, token[0]);
3585     _TripleTest(op2, ctx, token[0]);
3586 
3587     /* scan expected conditions */
3588     expstatus = scan_conditions(token+n);
3589 
3590 
3591     /* two distinct decimals */
3592     mpd_init_rand(tmp1);
3593     mpd_init_rand(tmp2);
3594     mpd_copy(tmp1, op1, ctx);
3595     mpd_copy(tmp2, op2, ctx);
3596     ctx->status = 0;
3597 
3598     int_result = func(tmp1, tmp2, ctx);
3599 
3600     snprintf(buf, 11, "%d", int_result);
3601     if (!(skip && int_result == INT_MAX)) { /* NaN cases are skipped for the int_retval */
3602         compare_expected(buf, expected, expstatus, token[0], ctx);
3603     }
3604     check_equalmem(tmp1, op1, token[0]);
3605     check_equalmem(tmp2, op2, token[0]);
3606 
3607     /* Allocation failures */
3608     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
3609         mpd_init_rand(tmp1);
3610         mpd_init_rand(tmp2);
3611         mpd_copy(tmp1, op1, ctx);
3612         mpd_copy(tmp2, op2, ctx);
3613         ctx->status = 0;
3614 
3615         mpd_set_alloc_fail(ctx);
3616         int_result = func(tmp1, tmp2, ctx);
3617         mpd_set_alloc(ctx);
3618 
3619         if (!(ctx->status&MPD_Malloc_error)) {
3620             break;
3621         }
3622         ASSERT(int_result== INT_MAX)
3623     }
3624     snprintf(buf, 11, "%d", int_result);
3625     if (!(skip && int_result == INT_MAX)) { /* NaN cases are skipped for the int_retval */
3626         compare_expected(buf, expected, expstatus, token[0], ctx);
3627     }
3628     check_equalmem(tmp1, op1, token[0]);
3629     check_equalmem(tmp2, op2, token[0]);
3630 }
3631 
3632 /*
3633  * Test a binary function that returns only an integer result.
3634  * Equal operands.
3635  * Used for the cmp functions.
3636  */
3637 static void
_Int_EqualBinop_Ctx(int skip,char * token[],int (* func)(const mpd_t *,const mpd_t *,mpd_context_t *),mpd_context_t * ctx)3638 _Int_EqualBinop_Ctx(int skip, char *token[], int (*func)(const mpd_t *, const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
3639 {
3640     mpd_context_t maxctx;
3641     int int_result;
3642     char buf[11];
3643     char *expected;
3644     uint32_t expstatus;
3645     int n;
3646 
3647     mpd_readcontext(&maxctx);
3648     maxctx.traps = MPD_Malloc_error;
3649 
3650     n = scan_1op_result(op, &expected, token, &maxctx);
3651     _TripleTest(op, ctx, token[0]);
3652 
3653     /* scan expected conditions */
3654     expstatus = scan_conditions(token+n);
3655 
3656 
3657     /* equal operands */
3658     mpd_init_rand(tmp);
3659     mpd_copy(tmp, op, ctx);
3660     ctx->status = 0;
3661 
3662     int_result = func(tmp, tmp, ctx);
3663 
3664     snprintf(buf, 11, "%d", int_result);
3665     if (!(skip && int_result == INT_MAX)) { /* NaN cases are skipped for the int_retval */
3666         compare_expected(buf, expected, expstatus, token[0], ctx);
3667     }
3668     check_equalmem(tmp, op, token[0]);
3669 
3670     /* Allocation failures */
3671     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
3672         mpd_init_rand(tmp);
3673         mpd_copy(tmp, op, ctx);
3674         ctx->status = 0;
3675 
3676         mpd_set_alloc_fail(ctx);
3677         int_result = func(tmp, tmp, ctx);
3678         mpd_set_alloc(ctx);
3679 
3680         if (!(ctx->status&MPD_Malloc_error)) {
3681             break;
3682         }
3683         ASSERT(int_result== INT_MAX)
3684     }
3685     snprintf(buf, 11, "%d", int_result);
3686     if (!(skip && int_result == INT_MAX)) { /* NaN cases are skipped for the int_retval */
3687         compare_expected(buf, expected, expstatus, token[0], ctx);
3688     }
3689     check_equalmem(tmp, op, token[0]);
3690 }
3691 
3692 /*
3693  * Test a binary function that returns an int.
3694  * The function does not take a context argument.
3695  */
3696 static void
_Int_Binop(char * token[],int (* func)(const mpd_t *,const mpd_t *),mpd_context_t * ctx)3697 _Int_Binop(char *token[], int (*func)(const mpd_t *, const mpd_t *), mpd_context_t *ctx)
3698 {
3699     mpd_context_t maxctx;
3700     int int_result;
3701     char buf[11];
3702     char *expected;
3703     uint32_t expstatus;
3704     int n;
3705 
3706     mpd_readcontext(&maxctx);
3707     maxctx.traps = MPD_Malloc_error;
3708 
3709     n = scan_2ops_result(op1, op2, &expected, token, &maxctx);
3710     _TripleTest(op1, ctx, token[0]);
3711     _TripleTest(op2, ctx, token[0]);
3712 
3713     /* scan expected conditions */
3714     expstatus = scan_conditions(token+n);
3715 
3716 
3717     /* two distinct decimals */
3718     mpd_init_rand(tmp1);
3719     mpd_init_rand(tmp2);
3720     mpd_copy(tmp1, op1, ctx);
3721     mpd_copy(tmp2, op2, ctx);
3722     ctx->status = 0;
3723 
3724     int_result = func(tmp1, tmp2);
3725 
3726     snprintf(buf, 11, "%d", int_result);
3727     compare_expected(buf, expected, expstatus, token[0], ctx);
3728     check_equalmem(tmp1, op1, token[0]);
3729     check_equalmem(tmp2, op2, token[0]);
3730 
3731     /* Allocation failures */
3732     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
3733         mpd_init_rand(tmp1);
3734         mpd_init_rand(tmp2);
3735         mpd_copy(tmp1, op1, ctx);
3736         mpd_copy(tmp2, op2, ctx);
3737         ctx->status = 0;
3738 
3739         mpd_set_alloc_fail(ctx);
3740         int_result = func(tmp1, tmp2);
3741         mpd_set_alloc(ctx);
3742 
3743         if (int_result != INT_MAX) {
3744             break;
3745         }
3746     }
3747     snprintf(buf, 11, "%d", int_result);
3748     compare_expected(buf, expected, expstatus, token[0], ctx);
3749     check_equalmem(tmp1, op1, token[0]);
3750     check_equalmem(tmp2, op2, token[0]);
3751 }
3752 
3753 /*
3754  * Test a binary function that returns an int.
3755  * Equal operands.
3756  * The function does not take a context argument.
3757  */
3758 static void
_Int_EqualBinop(char * token[],int (* func)(const mpd_t *,const mpd_t *),mpd_context_t * ctx)3759 _Int_EqualBinop(char *token[], int (*func)(const mpd_t *, const mpd_t *), mpd_context_t *ctx)
3760 {
3761     mpd_context_t maxctx;
3762     int int_result;
3763     char buf[11];
3764     char *expected;
3765     uint32_t expstatus;
3766     int n;
3767 
3768     mpd_readcontext(&maxctx);
3769     maxctx.traps = MPD_Malloc_error;
3770 
3771     n = scan_1op_result(op, &expected, token, &maxctx);
3772     _TripleTest(op, ctx, token[0]);
3773 
3774     /* scan expected conditions */
3775     expstatus = scan_conditions(token+n);
3776 
3777 
3778     /* equal operands */
3779     mpd_init_rand(tmp);
3780     mpd_copy(tmp, op, ctx);
3781     ctx->status = 0;
3782 
3783     int_result = func(tmp, tmp);
3784 
3785     snprintf(buf, 11, "%d", int_result);
3786     compare_expected(buf, expected, expstatus, token[0], ctx);
3787     check_equalmem(tmp, op, token[0]);
3788 
3789     /* Allocation failures */
3790     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
3791         mpd_init_rand(tmp);
3792         mpd_copy(tmp, op, ctx);
3793         ctx->status = 0;
3794 
3795         mpd_set_alloc_fail(ctx);
3796         int_result = func(tmp, tmp);
3797         mpd_set_alloc(ctx);
3798 
3799         if (int_result != INT_MAX) {
3800             break;
3801         }
3802     }
3803     snprintf(buf, 11, "%d", int_result);
3804     compare_expected(buf, expected, expstatus, token[0], ctx);
3805     check_equalmem(tmp, op, token[0]);
3806 }
3807 
3808 static mpd_ssize_t
scan_ssize(char * token[])3809 scan_ssize(char *token[])
3810 {
3811     errno = 0;
3812     if (token[1] == NULL) {
3813         errno = 1;
3814         return MPD_SSIZE_MAX;
3815     }
3816     return strtossize(token[1], NULL, 10);
3817 }
3818 
3819 static void
_mpd_shiftl(mpd_t * res,const mpd_t * a,mpd_ssize_t n,mpd_context_t * ctx)3820 _mpd_shiftl(mpd_t *res, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx)
3821 {
3822     ASSERT(!mpd_isspecial(a));
3823     mpd_shiftl(res, a, n, ctx);
3824 }
3825 
3826 static void
_mpd_shiftr(mpd_t * res,const mpd_t * a,mpd_ssize_t n,mpd_context_t * ctx)3827 _mpd_shiftr(mpd_t *res, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx)
3828 {
3829     ASSERT(!mpd_isspecial(a));
3830     (void)mpd_shiftr(res, a, n, ctx);
3831 }
3832 
3833 /*
3834  * Test a function with an mpd_t and an mpd_ssize_t operand.
3835  * Used for the shift functions.
3836  */
3837 static void
_Res_Op_Lsize_Ctx(int skip,char * token[],void (* func)(mpd_t *,const mpd_t *,mpd_ssize_t,mpd_context_t *),mpd_context_t * ctx)3838 _Res_Op_Lsize_Ctx(int skip, char *token[], void (*func)(mpd_t *, const mpd_t *, mpd_ssize_t, mpd_context_t *), mpd_context_t *ctx)
3839 {
3840     mpd_context_t maxctx;
3841     char *calc;
3842     char *expected;
3843     uint32_t expstatus;
3844     mpd_ssize_t ssize;
3845     int n;
3846 
3847     mpd_readcontext(&maxctx);
3848     maxctx.traps = MPD_Malloc_error;
3849 
3850     n = scan_2ops_result(op1, op2, &expected, token, &maxctx);
3851     _TripleTest(op1, ctx, token[0]);
3852     _TripleTest(op2, ctx, token[0]);
3853 
3854     /* scan expected conditions */
3855     expstatus = scan_conditions(token+n);
3856 
3857 
3858     /* only integers are allowed for ssize */
3859     if (skip && (mpd_isspecial(op2) || op2->exp != 0)) {
3860         /* fprintf(stderr, "SKIP: %s\n", token[0]); */
3861         return;
3862     }
3863     ssize = mpd_get_ssize(op2, &maxctx);
3864     if (maxctx.status&MPD_Invalid_operation) {
3865         return;
3866     }
3867 
3868     /* two distinct decimals */
3869     mpd_init_rand(tmp1);
3870     mpd_copy(tmp1, op1, ctx);
3871     mpd_init_rand(result);
3872     ctx->status = 0;
3873 
3874     func(result, tmp1, ssize, ctx);
3875 
3876     calc = _mpd_to_sci(result, 1);
3877     compare_expected(calc, expected, expstatus, token[0], ctx);
3878     mpd_free(calc);
3879     check_equalmem(tmp1, op1, token[0]);
3880 
3881     /* Allocation failures */
3882     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
3883         mpd_init_rand(tmp1);
3884         mpd_copy(tmp1, op1, ctx);
3885         mpd_minalloc(result);
3886         ctx->status = 0;
3887 
3888         mpd_set_alloc_fail(ctx);
3889         func(result, tmp1, ssize, ctx);
3890         mpd_set_alloc(ctx);
3891 
3892         if (!(ctx->status&MPD_Malloc_error)) {
3893             break;
3894         }
3895         ASSERT(mpd_isnan(result))
3896     }
3897     calc = _mpd_to_sci(result, 1);
3898     compare_expected(calc, expected, expstatus, token[0], ctx);
3899     mpd_free(calc);
3900     check_equalmem(tmp1, op1, token[0]);
3901 
3902 
3903     /* result == tmp1 */
3904     mpd_init_rand(tmp1);
3905     mpd_copy(tmp1, op1, ctx);
3906     ctx->status = 0;
3907 
3908     func(tmp1, tmp1, ssize, ctx);
3909 
3910     calc = _mpd_to_sci(tmp1, 1);
3911     compare_expected(calc, expected, expstatus, token[0], ctx);
3912     mpd_free(calc);
3913 
3914     /* Allocation failures */
3915     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
3916         mpd_init_rand(tmp1);
3917         mpd_copy(tmp1, op1, ctx);
3918         ctx->status = 0;
3919 
3920         mpd_set_alloc_fail(ctx);
3921         func(tmp1, tmp1, ssize, ctx);
3922         mpd_set_alloc(ctx);
3923 
3924         if (!(ctx->status&MPD_Malloc_error)) {
3925             break;
3926         }
3927         ASSERT(mpd_isnan(tmp1))
3928     }
3929     calc = _mpd_to_sci(tmp1, 1);
3930     compare_expected(calc, expected, expstatus, token[0], ctx);
3931     mpd_free(calc);
3932 }
3933 
3934 /* test mpd_qln10() */
3935 static void
_test_mpd_qln10(int skip,char * token[],mpd_context_t * ctx)3936 _test_mpd_qln10(int skip, char *token[], mpd_context_t *ctx)
3937 {
3938     mpd_context_t maxctx;
3939     char *calc;
3940     char *expected;
3941     uint32_t expstatus;
3942     mpd_ssize_t ssize;
3943     int n;
3944 
3945     mpd_readcontext(&maxctx);
3946     maxctx.traps = MPD_Malloc_error;
3947 
3948     n = scan_1op_result(op1, &expected, token, &maxctx);
3949     _TripleTest(op1, ctx, token[0]);
3950 
3951     /* scan expected conditions */
3952     expstatus = scan_conditions(token+n);
3953 
3954 
3955     /* only integers are allowed for ssize */
3956     if (skip && (mpd_isspecial(op1) || op1->exp != 0)) {
3957         /* fprintf(stderr, "SKIP: %s\n", token[0]); */
3958         return;
3959     }
3960     ssize = mpd_get_ssize(op1, &maxctx);
3961     if (maxctx.status&MPD_Invalid_operation) {
3962         return;
3963     }
3964 
3965     mpd_init_rand(result);
3966     ctx->status = 0;
3967 
3968     mpd_qln10(result, ssize, &ctx->status);
3969 
3970     calc = _mpd_to_sci(result, 1);
3971     compare_expected(calc, expected, expstatus, token[0], ctx);
3972     mpd_free(calc);
3973 
3974     /* Allocation failures */
3975     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
3976         mpd_minalloc(result);
3977         ctx->status = 0;
3978 
3979         mpd_set_alloc_fail(ctx);
3980         mpd_qln10(result, ssize, &ctx->status);
3981         mpd_set_alloc(ctx);
3982 
3983         if (!(ctx->status&MPD_Malloc_error)) {
3984             break;
3985         }
3986         ASSERT(mpd_isnan(result))
3987     }
3988     calc = _mpd_to_sci(result, 1);
3989     compare_expected(calc, expected, expstatus, token[0], ctx);
3990     mpd_free(calc);
3991 }
3992 
3993 static void
_Baseconv(char * token[],mpd_context_t * ctx)3994 _Baseconv(char *token[], mpd_context_t *ctx)
3995 {
3996     mpd_context_t maxctx;
3997     uint32_t base;
3998     uint16_t *data16;
3999     uint32_t *data32;
4000     size_t len16, len32;
4001     size_t expected_len16, expected_len32;
4002     char *expected;
4003     uint32_t expstatus;
4004     char *calc;
4005     int n = 0;
4006     int i, iter = 0;
4007 
4008     mpd_readcontext(&maxctx);
4009     maxctx.traps = MPD_Malloc_error;
4010 
4011     n = scan_1op_result(op1, &expected, token, &maxctx);
4012     ASSERT(mpd_isinteger(op1))
4013     _TripleTest(op1, ctx, token[0]);
4014 
4015     /* scan expected conditions */
4016     expstatus = scan_conditions(token+n);
4017 
4018     /*
4019      * base := (1<<15)
4020      * data16 := NULL
4021      * Allocation and deallocation on error by mpd_export_u16().
4022      */
4023     base = (1<<15);
4024     data16 = NULL;
4025     expected_len16 = mpd_export_u16(&data16, 0, base, op1, ctx);
4026     if (expected_len16 == SIZE_MAX) {
4027         mpd_err_fatal("export_to_base failed");
4028     }
4029 
4030     mpd_import_u16(result, data16, expected_len16, MPD_POS, base, ctx);
4031     calc = _mpd_to_sci(result, 1);
4032     compare_expected(calc, expected, expstatus, token[0], ctx);
4033 
4034     mpd_free(calc);
4035     mpd_free(data16);
4036 
4037     /*
4038      * base := (1<<15)
4039      * data16 := NULL
4040      * Test allocation failures.
4041      */
4042     base = (1<<15);
4043     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
4044         ctx->status = 0;
4045 
4046         mpd_set_alloc_fail(ctx);
4047         data16 = NULL;
4048         expected_len16 = mpd_export_u16(&data16, 0, base, op1, ctx);
4049         mpd_set_alloc(ctx);
4050 
4051         if (!(ctx->status&MPD_Malloc_error)) {
4052             break;
4053         }
4054         /* If data16 == NULL, it is deallocated on failure. */
4055         ASSERT(expected_len16 == SIZE_MAX)
4056     }
4057     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
4058         mpd_minalloc(result);
4059         ctx->status = 0;
4060 
4061         mpd_set_alloc_fail(ctx);
4062         mpd_import_u16(result, data16, expected_len16, MPD_POS, base, ctx);
4063         mpd_set_alloc(ctx);
4064 
4065         if (!(ctx->status&MPD_Malloc_error)) {
4066             break;
4067         }
4068         ASSERT(mpd_isnan(result))
4069     }
4070     calc = _mpd_to_sci(result, 1);
4071     compare_expected(calc, expected, expstatus, token[0], ctx);
4072     mpd_free(calc);
4073     mpd_free(data16);
4074 
4075     /*
4076      * base := (1<<15)
4077      * len(data16) := 1
4078      * Simulate result from sizeinbase() that is too small.
4079      */
4080     base = (1<<15);
4081     data16 = mpd_alloc(1, sizeof *data16);
4082     expected_len16 = mpd_export_u16(&data16, 1, base, op1, ctx);
4083     if (expected_len16 == SIZE_MAX) {
4084         mpd_err_fatal("export_to_base failed");
4085     }
4086 
4087     mpd_import_u16(result, data16, expected_len16, MPD_POS, base, ctx);
4088     calc = _mpd_to_sci(result, 1);
4089     compare_expected(calc, expected, expstatus, token[0], ctx);
4090 
4091     mpd_free(calc);
4092     mpd_free(data16);
4093 
4094     /*
4095      * base := (1<<15)
4096      * len(data16) == 1
4097      * Test allocation failures.
4098      */
4099     base = (1<<15);
4100     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
4101         ctx->status = 0;
4102 
4103         data16 = mpd_alloc(1, sizeof *data16);
4104         mpd_set_alloc_fail(ctx);
4105         expected_len16 = mpd_export_u16(&data16, 1, base, op1, ctx);
4106         mpd_set_alloc(ctx);
4107 
4108         if (!(ctx->status&MPD_Malloc_error)) {
4109             break;
4110         }
4111         /* Caller must free the memory that was passed in. */
4112         mpd_free(data16);
4113         ASSERT(expected_len16 == SIZE_MAX)
4114     }
4115     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
4116         mpd_minalloc(result);
4117         ctx->status = 0;
4118 
4119         mpd_set_alloc_fail(ctx);
4120         mpd_import_u16(result, data16, expected_len16, MPD_POS, base, ctx);
4121         mpd_set_alloc(ctx);
4122 
4123         if (!(ctx->status&MPD_Malloc_error)) {
4124             break;
4125         }
4126         ASSERT(mpd_isnan(result))
4127     }
4128     calc = _mpd_to_sci(result, 1);
4129     compare_expected(calc, expected, expstatus, token[0], ctx);
4130     mpd_free(calc);
4131     mpd_free(data16);
4132 
4133 
4134     /*
4135      * base := (1<<16)
4136      * len(data16) := mpd_sizeinbase()
4137      */
4138     base = (1U<<16);
4139     len16 = mpd_sizeinbase(op1, base);
4140     data16 = mpd_alloc((mpd_size_t)len16, sizeof *data16);
4141     len16 = mpd_export_u16(&data16, len16, base, op1, ctx);
4142     if (len16 == SIZE_MAX) {
4143         mpd_err_fatal("export_to_base failed");
4144     }
4145 
4146     mpd_import_u16(result, data16, len16, MPD_POS, base, ctx);
4147     calc = _mpd_to_sci(result, 1);
4148     compare_expected(calc, expected, expstatus, token[0], ctx);
4149 
4150     mpd_free(calc);
4151     mpd_free(data16);
4152 
4153 
4154     /*
4155      * base := 9999
4156      * len(data16) := mpd_sizeinbase()
4157      */
4158     base = 9999;
4159     len16 = mpd_sizeinbase(op1, base);
4160     data16 = mpd_alloc((mpd_size_t)len16, sizeof *data16);
4161     expected_len16 = mpd_export_u16(&data16, len16, base, op1, ctx);
4162     if (expected_len16 == SIZE_MAX) {
4163         mpd_err_fatal("export_to_base failed");
4164     }
4165 
4166     mpd_import_u16(result, data16, expected_len16, MPD_POS, base, ctx);
4167     calc = _mpd_to_sci(result, 1);
4168     compare_expected(calc, expected, expstatus, token[0], ctx);
4169 
4170     mpd_free(calc);
4171     mpd_free(data16);
4172 
4173 
4174     /*
4175      * base := [2..16]
4176      * len(data16) := mpd_sizeinbase()
4177      */
4178     iter = 16;
4179     for (i = 2; i <= iter; i++) {
4180 
4181         base = (uint32_t)i;
4182         len16 = mpd_sizeinbase(op1, base);
4183         data16 = mpd_alloc((mpd_size_t)len16, sizeof *data16);
4184         len16 = mpd_export_u16(&data16, len16, base, op1, ctx);
4185         if (len16 == SIZE_MAX) {
4186             mpd_err_fatal("export_to_base failed");
4187         }
4188 
4189         mpd_import_u16(result, data16, len16, MPD_POS, base, ctx);
4190         calc = _mpd_to_sci(result, 1);
4191         compare_expected(calc, expected, expstatus, token[0], ctx);
4192 
4193         mpd_free(calc);
4194         mpd_free(data16);
4195     }
4196 
4197     /*
4198      * base := random(UINT_16_MAX)
4199      * len(data16) := mpd_sizeinbase()
4200      */
4201     iter = 5;
4202     for (i = 0; i < iter; i++) {
4203 
4204         base = random() % UINT16_MAX;
4205         if (base < 2) base = 2;
4206 
4207         len16 = mpd_sizeinbase(op1, base);
4208         data16 = mpd_alloc((mpd_size_t)len16, sizeof *data16);
4209         len16 = mpd_export_u16(&data16, len16, base, op1, ctx);
4210         if (len16 == SIZE_MAX) {
4211             mpd_err_fatal("export_to_base failed");
4212         }
4213 
4214         mpd_import_u16(result, data16, len16, MPD_POS, base, ctx);
4215         calc = _mpd_to_sci(result, 1);
4216         compare_expected(calc, expected, expstatus, token[0], ctx);
4217 
4218         mpd_free(calc);
4219         mpd_free(data16);
4220 
4221         for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
4222             ctx->status = 0;
4223 
4224             data16 = mpd_alloc(1, sizeof *data16);
4225             mpd_set_alloc_fail(ctx);
4226             expected_len16 = mpd_export_u16(&data16, 1, base, op1, ctx);
4227             mpd_set_alloc(ctx);
4228 
4229             if (!(ctx->status&MPD_Malloc_error)) {
4230                 break;
4231             }
4232             /* Caller must free the memory that was passed in. */
4233             mpd_free(data16);
4234             ASSERT(expected_len16 == SIZE_MAX)
4235         }
4236         for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
4237             mpd_minalloc(result);
4238             ctx->status = 0;
4239 
4240             mpd_set_alloc_fail(ctx);
4241             mpd_import_u16(result, data16, expected_len16, MPD_POS, base, ctx);
4242             mpd_set_alloc(ctx);
4243 
4244             if (!(ctx->status&MPD_Malloc_error)) {
4245                 break;
4246             }
4247             ASSERT(mpd_isnan(result))
4248         }
4249         calc = _mpd_to_sci(result, 1);
4250         compare_expected(calc, expected, expstatus, token[0], ctx);
4251         mpd_free(calc);
4252         mpd_free(data16);
4253 
4254         for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
4255             ctx->status = 0;
4256 
4257             data16 = mpd_alloc(1, sizeof *data16);
4258             mpd_set_alloc_fail(ctx);
4259             expected_len16 = mpd_export_u16(&data16, 1, base, op1, ctx);
4260             mpd_set_alloc(ctx);
4261 
4262             if (!(ctx->status&MPD_Malloc_error)) {
4263                 break;
4264             }
4265             /* Caller must free the memory that was passed in. */
4266             mpd_free(data16);
4267             ASSERT(expected_len16 == SIZE_MAX)
4268         }
4269         for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
4270             mpd_minalloc(result);
4271             ctx->status = 0;
4272 
4273             mpd_set_alloc_fail(ctx);
4274             mpd_import_u16(result, data16, expected_len16, MPD_POS, base, ctx);
4275             mpd_set_alloc(ctx);
4276 
4277             if (!(ctx->status&MPD_Malloc_error)) {
4278                 break;
4279             }
4280             ASSERT(mpd_isnan(result))
4281         }
4282         calc = _mpd_to_sci(result, 1);
4283         compare_expected(calc, expected, expstatus, token[0], ctx);
4284         mpd_free(calc);
4285         mpd_free(data16);
4286     }
4287 
4288     /* ================================================================ */
4289     /*                         uint32_t bases                           */
4290     /* ================================================================ */
4291 
4292     /*
4293      * base := (1<<30)
4294      * data32 := NULL
4295      */
4296     base = (1<<30);
4297     data32 = NULL;
4298     expected_len32 = mpd_export_u32(&data32, 0, base, op1, ctx);
4299     if (expected_len32 == SIZE_MAX) {
4300         mpd_err_fatal("export_to_base failed");
4301     }
4302 
4303     mpd_import_u32(result, data32, expected_len32, MPD_POS, base, ctx);
4304     calc = _mpd_to_sci(result, 1);
4305     compare_expected(calc, expected, expstatus, token[0], ctx);
4306 
4307     mpd_free(calc);
4308     mpd_free(data32);
4309 
4310     /*
4311      * base := (1<<30)
4312      * data32 := NULL
4313      * Test allocation failures. */
4314     base = (1<<30);
4315     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
4316         ctx->status = 0;
4317 
4318         mpd_set_alloc_fail(ctx);
4319         data32 = NULL;
4320         expected_len32 = mpd_export_u32(&data32, 0, base, op1, ctx);
4321         mpd_set_alloc(ctx);
4322 
4323         if (!(ctx->status&MPD_Malloc_error)) {
4324             break;
4325         }
4326         ASSERT(expected_len32 == SIZE_MAX)
4327     }
4328     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
4329         mpd_minalloc(result);
4330         ctx->status = 0;
4331 
4332         mpd_set_alloc_fail(ctx);
4333         mpd_import_u32(result, data32, expected_len32, MPD_POS, base, ctx);
4334         mpd_set_alloc(ctx);
4335 
4336         if (!(ctx->status&MPD_Malloc_error)) {
4337             break;
4338         }
4339         ASSERT(mpd_isnan(result))
4340     }
4341     calc = _mpd_to_sci(result, 1);
4342     compare_expected(calc, expected, expstatus, token[0], ctx);
4343     mpd_free(calc);
4344     mpd_free(data32);
4345 
4346 
4347     /*
4348      * base := (1<<30)
4349      * len(data32) := 1
4350      */
4351     base = (1<<30);
4352     data32 = mpd_alloc(1, sizeof *data32);
4353     expected_len32 = mpd_export_u32(&data32, 1, base, op1, ctx);
4354     if (expected_len32 == SIZE_MAX) {
4355         mpd_err_fatal("export_to_base failed");
4356     }
4357 
4358     mpd_import_u32(result, data32, expected_len32, MPD_POS, base, ctx);
4359     calc = _mpd_to_sci(result, 1);
4360     compare_expected(calc, expected, expstatus, token[0], ctx);
4361 
4362     mpd_free(calc);
4363     mpd_free(data32);
4364 
4365     /*
4366      * base := (1<<30)
4367      * len(data32) := 1
4368      * Test allocation failures.
4369      */
4370     base = (1<<30);
4371     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
4372         ctx->status = 0;
4373 
4374         data32 = mpd_alloc(1, sizeof *data32);
4375         mpd_set_alloc_fail(ctx);
4376         expected_len32 = mpd_export_u32(&data32, 1, base, op1, ctx);
4377         mpd_set_alloc(ctx);
4378 
4379         if (!(ctx->status&MPD_Malloc_error)) {
4380             break;
4381         }
4382         ASSERT(expected_len32 == SIZE_MAX)
4383         mpd_free(data32);
4384     }
4385     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
4386         mpd_minalloc(result);
4387         ctx->status = 0;
4388 
4389         mpd_set_alloc_fail(ctx);
4390         mpd_import_u32(result, data32, expected_len32, MPD_POS, base, ctx);
4391         mpd_set_alloc(ctx);
4392 
4393         if (!(ctx->status&MPD_Malloc_error)) {
4394             break;
4395         }
4396         ASSERT(mpd_isnan(result))
4397     }
4398     calc = _mpd_to_sci(result, 1);
4399     compare_expected(calc, expected, expstatus, token[0], ctx);
4400     mpd_free(calc);
4401     mpd_free(data32);
4402 
4403 
4404     /*
4405      * base := 10**9
4406      * len(data32) := mpd_sizeinbase()
4407      */
4408     base = 1000000000;
4409     len32 = mpd_sizeinbase(op1, base);
4410     data32 = mpd_alloc((mpd_size_t)len32, sizeof *data32);
4411     expected_len32 = mpd_export_u32(&data32, len32, base, op1, ctx);
4412     if (len32 == SIZE_MAX) {
4413         mpd_err_fatal("export_to_base failed");
4414     }
4415 
4416     mpd_import_u32(result, data32, expected_len32, MPD_POS, base, ctx);
4417     calc = _mpd_to_sci(result, 1);
4418     compare_expected(calc, expected, expstatus, token[0], ctx);
4419 
4420     mpd_free(calc);
4421     mpd_free(data32);
4422 
4423     /*
4424      * base := 10**9
4425      * len(data32) := mpd_sizeinbase()
4426      * Test allocation failures.
4427      */
4428     base = 1000000000;
4429     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
4430         ctx->status = 0;
4431 
4432         mpd_set_alloc_fail(ctx);
4433         data32 = NULL;
4434         expected_len32 = mpd_export_u32(&data32, 0, base, op1, ctx);
4435         mpd_set_alloc(ctx);
4436 
4437         if (!(ctx->status&MPD_Malloc_error)) {
4438             break;
4439         }
4440         ASSERT(expected_len32 == SIZE_MAX)
4441     }
4442     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
4443         mpd_minalloc(result);
4444         ctx->status = 0;
4445 
4446         mpd_set_alloc_fail(ctx);
4447         mpd_import_u32(result, data32, expected_len32, MPD_POS, base, ctx);
4448         mpd_set_alloc(ctx);
4449 
4450         if (!(ctx->status&MPD_Malloc_error)) {
4451             break;
4452         }
4453         ASSERT(mpd_isnan(result))
4454     }
4455     calc = _mpd_to_sci(result, 1);
4456     compare_expected(calc, expected, expstatus, token[0], ctx);
4457     mpd_free(calc);
4458     mpd_free(data32);
4459 
4460     /*
4461      * base := 10**9
4462      * len(data32) := 1
4463      * Test allocation failures.
4464      */
4465     base = 1000000000;
4466     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
4467         ctx->status = 0;
4468 
4469         data32 = mpd_alloc(1, sizeof *data32);
4470         mpd_set_alloc_fail(ctx);
4471         expected_len32 = mpd_export_u32(&data32, 1, base, op1, ctx);
4472         mpd_set_alloc(ctx);
4473 
4474         if (!(ctx->status&MPD_Malloc_error)) {
4475             break;
4476         }
4477         ASSERT(expected_len32 == SIZE_MAX)
4478         mpd_free(data32);
4479     }
4480     for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
4481         mpd_minalloc(result);
4482         ctx->status = 0;
4483 
4484         mpd_set_alloc_fail(ctx);
4485         mpd_import_u32(result, data32, expected_len32, MPD_POS, base, ctx);
4486         mpd_set_alloc(ctx);
4487 
4488         if (!(ctx->status&MPD_Malloc_error)) {
4489             break;
4490         }
4491         ASSERT(mpd_isnan(result))
4492     }
4493     calc = _mpd_to_sci(result, 1);
4494     compare_expected(calc, expected, expstatus, token[0], ctx);
4495     mpd_free(calc);
4496     mpd_free(data32);
4497 
4498     for (i = 2; i <= 16; i++) {
4499 
4500         base = (uint32_t)i;
4501         len32 = mpd_sizeinbase(op1, base);
4502         data32 = mpd_alloc((mpd_size_t)len32, sizeof *data32);
4503         expected_len32 = mpd_export_u32(&data32, len32, base, op1, ctx);
4504         if (len32 == SIZE_MAX) {
4505             mpd_err_fatal("export_to_base failed");
4506         }
4507 
4508         mpd_import_u32(result, data32, expected_len32, MPD_POS, base, ctx);
4509         calc = _mpd_to_sci(result, 1);
4510         compare_expected(calc, expected, expstatus, token[0], ctx);
4511 
4512         mpd_free(calc);
4513         mpd_free(data32);
4514     }
4515 
4516     for (i = 0; i < 5; i++) {
4517 
4518         base = random() % UINT32_MAX;
4519         if (base < 2) base = 2;
4520 
4521         len32 = mpd_sizeinbase(op1, base);
4522         data32 = mpd_alloc((mpd_size_t)len32, sizeof *data32);
4523         expected_len32 = mpd_export_u32(&data32, len32, base, op1, ctx);
4524         if (len32 == SIZE_MAX) {
4525             mpd_err_fatal("export_to_base failed");
4526         }
4527 
4528         mpd_import_u32(result, data32, expected_len32, MPD_POS, base, ctx);
4529         calc = _mpd_to_sci(result, 1);
4530         compare_expected(calc, expected, expstatus, token[0], ctx);
4531 
4532         mpd_free(calc);
4533         mpd_free(data32);
4534 
4535         for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
4536             ctx->status = 0;
4537 
4538             data32 = mpd_alloc(1, sizeof *data32);
4539             mpd_set_alloc_fail(ctx);
4540             expected_len32 = mpd_export_u32(&data32, 1, base, op1, ctx);
4541             mpd_set_alloc(ctx);
4542 
4543             if (!(ctx->status&MPD_Malloc_error)) {
4544                 break;
4545             }
4546             ASSERT(expected_len32 == SIZE_MAX)
4547             mpd_free(data32);
4548         }
4549         for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
4550             mpd_minalloc(result);
4551             ctx->status = 0;
4552 
4553             mpd_set_alloc_fail(ctx);
4554             mpd_import_u32(result, data32, expected_len32, MPD_POS, base, ctx);
4555             mpd_set_alloc(ctx);
4556 
4557             if (!(ctx->status&MPD_Malloc_error)) {
4558                 break;
4559             }
4560             ASSERT(mpd_isnan(result))
4561         }
4562         calc = _mpd_to_sci(result, 1);
4563         compare_expected(calc, expected, expstatus, token[0], ctx);
4564         mpd_free(calc);
4565         mpd_free(data32);
4566 
4567         for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
4568             ctx->status = 0;
4569 
4570             data32 = mpd_alloc(1, sizeof *data32);
4571             mpd_set_alloc_fail(ctx);
4572             expected_len32 = mpd_export_u32(&data32, 1, base, op1, ctx);
4573             mpd_set_alloc(ctx);
4574 
4575             if (!(ctx->status&MPD_Malloc_error)) {
4576                 break;
4577             }
4578             ASSERT(expected_len32 == SIZE_MAX)
4579             mpd_free(data32);
4580         }
4581         for (alloc_fail = 1; alloc_fail < INT_MAX; alloc_fail++) {
4582             mpd_minalloc(result);
4583             ctx->status = 0;
4584 
4585             mpd_set_alloc_fail(ctx);
4586             mpd_import_u32(result, data32, expected_len32, MPD_POS, base, ctx);
4587             mpd_set_alloc(ctx);
4588 
4589             if (!(ctx->status&MPD_Malloc_error)) {
4590                 break;
4591             }
4592             ASSERT(mpd_isnan(result))
4593         }
4594         calc = _mpd_to_sci(result, 1);
4595         compare_expected(calc, expected, expstatus, token[0], ctx);
4596         mpd_free(calc);
4597         mpd_free(data32);
4598     }
4599 }
4600 
4601 /*
4602  * Test a function returning a uint64_t, accepting:
4603  *     op, context
4604  *
4605  * This function is used for:
4606  *   - mpd_get_uint (64 bit)
4607  *   - mpd_abs_uint (64 bit)
4608  *   - mpd_get_u64
4609  */
4610 #ifndef MPD_LEGACY_COMPILER
4611 static void
_u64_MpdCtx(char ** token,uint64_t (* func)(const mpd_t *,mpd_context_t *),mpd_context_t * ctx)4612 _u64_MpdCtx(char **token, uint64_t (*func)(const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
4613 {
4614     mpd_context_t maxctx;
4615     uint64_t calc_uint;
4616     char calc[23];
4617     char *expected;
4618     uint32_t expstatus;
4619     int n;
4620 
4621     mpd_readcontext(&maxctx);
4622     maxctx.traps = MPD_Malloc_error;
4623 
4624     /* conversion should be done as if there were no limits */
4625     n = scan_1op_result(op, &expected, token, &maxctx);
4626     _TripleTest(op, ctx, token[0]);
4627 
4628     expstatus = scan_conditions(token+n);
4629 
4630     mpd_init_rand(tmp);
4631     mpd_copy(tmp, op, ctx);
4632     ctx->status = 0;
4633 
4634     calc_uint = func(tmp, ctx);
4635     snprintf(calc, 23, "%" PRIu64, calc_uint);
4636 
4637     /* compare the calculated result to the expected result */
4638     compare_expected(calc, expected, expstatus, token[0], ctx);
4639     check_equalmem(tmp, op, token[0]);
4640 }
4641 #endif
4642 
4643 /*
4644  * Test a function returning a uint64_t, accepting:
4645  *     op, context
4646  *
4647  * This function is used for:
4648  *   - mpd_get_uint (64 bit)
4649  *   - mpd_abs_uint (64 bit)
4650  *   - mpd_get_u64
4651  */
4652 static void
_u32_MpdCtx(char ** token,uint32_t (* func)(const mpd_t *,mpd_context_t *),mpd_context_t * ctx)4653 _u32_MpdCtx(char **token, uint32_t (*func)(const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
4654 {
4655     mpd_context_t maxctx;
4656     uint32_t calc_uint;
4657     char calc[23];
4658     char *expected;
4659     uint32_t expstatus;
4660     int n;
4661 
4662     mpd_readcontext(&maxctx);
4663     maxctx.traps = MPD_Malloc_error;
4664 
4665     /* conversion should be done as if there were no limits */
4666     n = scan_1op_result(op, &expected, token, &maxctx);
4667     _TripleTest(op, ctx, token[0]);
4668 
4669     expstatus = scan_conditions(token+n);
4670 
4671     mpd_init_rand(tmp);
4672     mpd_copy(tmp, op, ctx);
4673     ctx->status = 0;
4674 
4675     calc_uint = func(tmp, ctx);
4676     snprintf(calc, 23, "%" PRIu32, calc_uint);
4677 
4678     /* compare the calculated result to the expected result */
4679     compare_expected(calc, expected, expstatus, token[0], ctx);
4680     check_equalmem(tmp, op, token[0]);
4681 }
4682 
4683 /*
4684  * Test a function returning an mpd_ssize_t, accepting:
4685  *     op, fmt, context
4686  *
4687  * This function is used for:
4688  *   - mpd_get_ssize
4689  *   - mpd_get_i64
4690  *   - mpd_get_i32
4691  */
4692 #ifndef MPD_LEGACY_COMPILER
4693 static void
_i64_MpdCtx(char ** token,int64_t (* func)(const mpd_t *,mpd_context_t *),mpd_context_t * ctx)4694 _i64_MpdCtx(char **token, int64_t (*func)(const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
4695 {
4696     mpd_context_t maxctx;
4697     int64_t calc_ssize;
4698     char calc[23];
4699     char *expected;
4700     uint32_t expstatus;
4701     int n;
4702 
4703     mpd_readcontext(&maxctx);
4704     maxctx.traps = MPD_Malloc_error;
4705 
4706     /* conversion should be done as if there were no limits */
4707     n = scan_1op_result(op, &expected, token, &maxctx);
4708     _TripleTest(op, ctx, token[0]);
4709 
4710     expstatus = scan_conditions(token+n);
4711 
4712     mpd_init_rand(tmp);
4713     mpd_copy(tmp, op, ctx);
4714     ctx->status = 0;
4715 
4716     calc_ssize = func(tmp, ctx);
4717     snprintf(calc, 23, "%" PRIi64, calc_ssize);
4718 
4719     /* compare the calculated result to the expected result */
4720     compare_expected(calc, expected, expstatus, token[0], ctx);
4721     check_equalmem(tmp, op, token[0]);
4722 }
4723 #endif
4724 
4725 /*
4726  * Test a function returning an mpd_ssize_t, accepting:
4727  *     op, fmt, context
4728  *
4729  * This function is used for:
4730  *   - mpd_get_ssize
4731  *   - mpd_get_i64
4732  *   - mpd_get_i32
4733  */
4734 static void
_i32_MpdCtx(char ** token,int32_t (* func)(const mpd_t *,mpd_context_t *),mpd_context_t * ctx)4735 _i32_MpdCtx(char **token, int32_t (*func)(const mpd_t *, mpd_context_t *), mpd_context_t *ctx)
4736 {
4737     mpd_context_t maxctx;
4738     int32_t calc_ssize;
4739     char calc[23];
4740     char *expected;
4741     uint32_t expstatus;
4742     int n;
4743 
4744     mpd_readcontext(&maxctx);
4745     maxctx.traps = MPD_Malloc_error;
4746 
4747     /* conversion should be done as if there were no limits */
4748     n = scan_1op_result(op, &expected, token, &maxctx);
4749     _TripleTest(op, ctx, token[0]);
4750 
4751     expstatus = scan_conditions(token+n);
4752 
4753     mpd_init_rand(tmp);
4754     mpd_copy(tmp, op, ctx);
4755     ctx->status = 0;
4756 
4757     calc_ssize = func(tmp, ctx);
4758     snprintf(calc, 23, "%" PRIi32, calc_ssize);
4759 
4760     /* compare the calculated result to the expected result */
4761     compare_expected(calc, expected, expstatus, token[0], ctx);
4762     check_equalmem(tmp, op, token[0]);
4763 }
4764 
4765 static void
triple_cov(void)4766 triple_cov(void)
4767 {
4768     mpd_uint128_triple_t triple = { MPD_TRIPLE_QNAN, 2, 0, 0, 0 };
4769     uint32_t status = 0;
4770 
4771     mpd_from_uint128_triple(op, &triple, &status);
4772     ASSERT(status == MPD_Conversion_syntax)
4773     ASSERT(mpd_isqnan(op))
4774 
4775     triple.sign = 0;
4776     triple.exp = 1;
4777     status = 0;
4778     mpd_from_uint128_triple(op, &triple, &status);
4779     ASSERT(status == MPD_Conversion_syntax)
4780     ASSERT(mpd_isqnan(op))
4781 
4782     triple.tag = MPD_TRIPLE_INF;
4783     status = 0;
4784     mpd_from_uint128_triple(op, &triple, &status);
4785     ASSERT(status == MPD_Conversion_syntax)
4786     ASSERT(mpd_isqnan(op))
4787 
4788     triple.tag = MPD_TRIPLE_NORMAL;
4789     triple.sign = 2;
4790     status = 0;
4791     mpd_from_uint128_triple(op, &triple, &status);
4792     ASSERT(status == MPD_Conversion_syntax)
4793     ASSERT(mpd_isqnan(op))
4794 
4795     triple.tag = MPD_TRIPLE_NORMAL;
4796     triple.sign = 0;
4797     triple.exp = INT64_MAX;
4798     status = 0;
4799     mpd_from_uint128_triple(op, &triple, &status);
4800     ASSERT(status == MPD_Conversion_syntax)
4801     ASSERT(mpd_isqnan(op))
4802 
4803     triple.tag = MPD_TRIPLE_NORMAL;
4804     triple.sign = 0;
4805     triple.exp = INT64_MIN;
4806     status = 0;
4807     mpd_from_uint128_triple(op, &triple, &status);
4808     ASSERT(status == MPD_Conversion_syntax)
4809     ASSERT(mpd_isqnan(op))
4810 
4811     triple.tag = MPD_TRIPLE_NORMAL;
4812     triple.sign = 0;
4813     triple.exp = MPD_SSIZE_MAX;
4814     status = 0;
4815     mpd_from_uint128_triple(op, &triple, &status);
4816     ASSERT(status == MPD_Conversion_syntax)
4817     ASSERT(mpd_isqnan(op))
4818 
4819     triple.tag = MPD_TRIPLE_NORMAL;
4820     triple.sign = 0;
4821     triple.exp = MPD_SSIZE_MIN;
4822     status = 0;
4823     mpd_from_uint128_triple(op, &triple, &status);
4824     ASSERT(status == MPD_Conversion_syntax)
4825     ASSERT(mpd_isqnan(op))
4826 
4827     triple.tag = (enum mpd_triple_class)10;
4828     triple.sign = 0;
4829     status = 0;
4830     mpd_from_uint128_triple(op, &triple, &status);
4831     ASSERT(status == MPD_Conversion_syntax)
4832     ASSERT(mpd_isqnan(op))
4833 }
4834 
4835 
4836 /* process a file */
4837 static void
doit(const char * filename)4838 doit(const char *filename)
4839 {
4840     FILE *file;
4841     mpd_context_t ctx;
4842     char *line;
4843     char *tmpline;
4844     char *token[MAXTOKEN+1];
4845     uint32_t testno;
4846     mpd_ssize_t l;
4847 
4848 
4849     mpd_testcontext(&ctx);
4850 
4851     ctx.traps = MPD_Malloc_error;
4852 
4853     file_failure = 0;
4854     if (strcmp(filename, "-") == 0) {
4855         file = stdin;
4856     }
4857     else {
4858         if ((file = fopen(filename, "r")) == NULL) {
4859             mpd_err_fatal("could not open %s", filename);
4860         }
4861         if (!startswith(filename, "official") && !startswith(filename, "additional")) {
4862             printf("%s ...", filename);
4863             fflush(stdout);
4864         }
4865     }
4866 
4867     if ((line = mpd_alloc(MAXLINE+1, sizeof *line)) == NULL) {
4868         mpd_err_fatal("out of memory");
4869     }
4870     if ((tmpline = mpd_alloc(MAXLINE+1, sizeof *line)) == NULL) {
4871         mpd_err_fatal("out of memory");
4872     }
4873 
4874 
4875     while (fgets(line, MAXLINE+1, file) != NULL) {
4876 
4877         /* split a line into tokens */
4878         strcpy(tmpline, line);
4879 
4880         for (int i =0; i < MAXTOKEN+1; i++) {
4881             token[i] = NULL;
4882         }
4883 
4884         if (split(token, tmpline) == 0) {
4885             goto cleanup;
4886         }
4887 
4888 
4889         /* comments */
4890         if (startswith(token[0], "--")) {
4891             goto cleanup;
4892         }
4893         /* end comments */
4894 
4895         /* skip bool* tests in extra.decTest */
4896         if (startswith(token[0], "bool")) {
4897             goto cleanup;
4898         }
4899         /* end skips */
4900 
4901 
4902         /* directives */
4903         if (startswith(token[0], "ExtendedRange")) {
4904             ASSERT(token[1] != NULL);
4905             if (strcmp(token[1], "1") == 0) {
4906                 extended = 1;
4907             }
4908             else if (strcmp(token[1], "0") == 0) {
4909                 extended = 0;
4910             }
4911             else {
4912                 mpd_err_fatal("%s: %s", filename, line);
4913             }
4914             goto cleanup;
4915         }
4916 
4917         if (startswith(token[0], "Precision")) {
4918             ASSERT(token[1] != NULL);
4919             if (strcmp(token[1], "MAX_PREC") == 0) {
4920                 l = MPD_MAX_PREC;
4921             }
4922             else {
4923                 l = scan_ssize(token);
4924                 if (errno != 0) {
4925                     mpd_err_fatal("%s: %s", filename, line);
4926                 }
4927             }
4928             ctx.prec = l;
4929             goto cleanup;
4930         }
4931 
4932         if (startswith(token[0], "Rounding")) {
4933             ASSERT(token[1] != NULL);
4934             if (eqtoken(token[1], "Ceiling"))
4935                 ctx.round = MPD_ROUND_CEILING;
4936             else if (eqtoken(token[1], "Up"))
4937                 ctx.round = MPD_ROUND_UP;
4938             else if (eqtoken(token[1], "Half_up"))
4939                 ctx.round = MPD_ROUND_HALF_UP;
4940             else if (eqtoken(token[1], "Half_even"))
4941                 ctx.round = MPD_ROUND_HALF_EVEN;
4942             else if (eqtoken(token[1], "Half_down"))
4943                 ctx.round = MPD_ROUND_HALF_DOWN;
4944             else if (eqtoken(token[1], "Down"))
4945                 ctx.round = MPD_ROUND_DOWN;
4946             else if (eqtoken(token[1], "Floor"))
4947                 ctx.round = MPD_ROUND_FLOOR;
4948             else if (eqtoken(token[1], "05up"))
4949                 ctx.round = MPD_ROUND_05UP;
4950             else
4951                 mpd_err_fatal("%s: %s", filename, line);
4952             goto cleanup;
4953         }
4954 
4955         if (startswith(token[0], "MaxExponent")) {
4956             ASSERT(token[1] != NULL);
4957             if (strcmp(token[1], "MAX_EMAX") == 0) {
4958                 l = MPD_MAX_EMAX;
4959             }
4960             else {
4961                 l = scan_ssize(token);
4962                 if (errno != 0) {
4963                     mpd_err_fatal("%s: %s", filename, line);
4964                 }
4965             }
4966             ctx.emax = l;
4967             goto cleanup;
4968         }
4969 
4970         if (startswith(token[0], "MinExponent")) {
4971             ASSERT(token[1] != NULL);
4972             if (strcmp(token[1], "MIN_EMIN") == 0) {
4973                 l = MPD_MIN_EMIN;
4974             }
4975             else {
4976                 l = scan_ssize(token);
4977                 if (errno != 0) {
4978                     mpd_err_fatal("%s: %s", filename, line);
4979                 }
4980             }
4981             ctx.emin = l;
4982             goto cleanup;
4983         }
4984 
4985         if (startswith(token[0], "Dectest")) {
4986             ASSERT(token[1] != NULL);
4987             if (token[1] == NULL) {
4988                 mpd_err_fatal("%s: %s", filename, line);
4989             }
4990             doit(token[1]);
4991             goto cleanup;
4992         }
4993         /* end directives */
4994 
4995         /* optional directives */
4996         if (startswith(token[0], "Version")) {
4997             goto cleanup;
4998         }
4999 
5000         if (startswith(token[0], "Extended")) {
5001             goto cleanup;
5002         }
5003 
5004         if (startswith(token[0], "Clamp")) {
5005             ASSERT(token[1] != NULL);
5006             l = scan_ssize(token);
5007             if (errno != 0) {
5008                 mpd_err_fatal("%s: %s", filename, line);
5009             }
5010             if (!mpd_qsetclamp(&ctx, (int)l)) {
5011                 mpd_err_fatal("%s: %s", filename, line);
5012             }
5013             goto cleanup;
5014         }
5015         if (startswith(token[0], "Locale")) {
5016             ASSERT(token[1] != NULL);
5017             if (token[1] == NULL) {
5018                 mpd_err_fatal("%s: %s", filename, line);
5019             }
5020             if (extended) {
5021                 printf("locale: %s\n", token[1]);
5022                 fflush(stdout);
5023             }
5024             if (setlocale(LC_NUMERIC, token[1]) == NULL) {
5025                 mpd_err_fatal("%s: %s", filename, line);
5026             }
5027             goto cleanup;
5028         }
5029 
5030         mpd_assert_context_ok(&ctx);
5031         /* end optional directives */
5032 
5033 
5034         /*
5035          * Actual tests start here:
5036          *   - token[0] is the id
5037          *   - token[1] is the operation type
5038          *   - testno can be used for setting a watchpoint in the debugger
5039          */
5040         testno = (uint32_t)get_testno(token[0]);
5041         (void)testno;
5042 
5043         /* The id is in the skip list */
5044         if (check_skip(token[0])) {
5045             goto cleanup;
5046         }
5047 #ifdef MPD_CONFIG_64
5048         /* Skip 32-bit specific coverage tests. */
5049         if (startswith(token[0], "cov32")) {
5050             goto cleanup;
5051         }
5052 #else
5053         /* Skip 64-bit specific coverage tests. */
5054         if (startswith(token[0], "cov64")) {
5055             goto cleanup;
5056         }
5057 #endif
5058         /* Translate operation type for powmod */
5059         if (startswith(token[0], "pwmx")) {
5060             free(token[1]);
5061             token[1] = malloc(sizeof("powmod"));
5062             strcpy(token[1], "powmod");
5063         }
5064         /* end skips */
5065 
5066 
5067         /* Unary functions with char * result */
5068         if (eqtoken(token[1], "tosci") || eqtoken(token[1], "apply")) {
5069             _cp_MpdCtx(token, mpd_to_sci, &ctx);
5070             sci_eng_size(token, mpd_to_sci_size, &ctx);
5071         }
5072         else if (eqtoken(token[1], "toeng")) {
5073             _cp_MpdCtx(token, mpd_to_eng, &ctx);
5074             sci_eng_size(token, mpd_to_eng_size, &ctx);
5075         }
5076         else if (eqtoken(token[1], "format")) {
5077             _cp_MpdFmtCtx(token, mpd_format, &ctx);
5078         }
5079         /* Unary function with const char * result */
5080         else if (eqtoken(token[1], "class")) {
5081             _ccp_MpdCtx(token, mpd_class, &ctx);
5082         }
5083 
5084         /* Unary functions with mpd_t * result */
5085         else if (eqtoken(token[1], "abs")) {
5086             _Res_Op_Ctx(token, mpd_abs, &ctx);
5087         }
5088         else if (eqtoken(token[1], "copy")) {
5089             _Res_Op_Ctx(token, mpd_copy, &ctx);
5090         }
5091         else if (eqtoken(token[1], "copyabs")) {
5092             _Res_Op_Ctx(token, mpd_copy_abs, &ctx);
5093         }
5094         else if (eqtoken(token[1], "copynegate")) {
5095             _Res_Op_Ctx(token, mpd_copy_negate, &ctx);
5096         }
5097         else if (eqtoken(token[1], "exp")) {
5098             if (extended) {
5099                 if (testno != 126) {
5100                     ctx.allcr = 0;
5101                     /* exp: err < 1ulp, but not correctly rounded */
5102                     _Res_Op_Ctx(token, mpd_exp, &ctx);
5103                     ctx.allcr = 1;
5104                 }
5105             }
5106             _Res_Op_Ctx(token, mpd_exp, &ctx);
5107         }
5108         else if (eqtoken(token[1], "invert")) {
5109             _Res_Op_Ctx(token, mpd_invert, &ctx);
5110         }
5111         else if (eqtoken(token[1], "invroot")) {
5112             _Res_Op_Ctx(token, mpd_invroot, &ctx);
5113         }
5114         else if (eqtoken(token[1], "ln")) {
5115             if (extended) {
5116                 ctx.allcr = 0;
5117                 _Res_Op_Ctx(token, mpd_ln, &ctx);
5118                 ctx.allcr = 1;
5119             }
5120             _Res_Op_Ctx(token, mpd_ln, &ctx);
5121         }
5122         else if (eqtoken(token[1], "log10")) {
5123             if (extended) {
5124                 ctx.allcr = 0;
5125                 _Res_Op_Ctx(token, mpd_log10, &ctx);
5126                 ctx.allcr = 1;
5127             }
5128             _Res_Op_Ctx(token, mpd_log10, &ctx);
5129         }
5130         else if (eqtoken(token[1], "logb")) {
5131             _Res_Op_Ctx(token, mpd_logb, &ctx);
5132         }
5133         else if (eqtoken(token[1], "minus")) {
5134             _Res_Op_Ctx(token, mpd_minus, &ctx);
5135         }
5136         else if (eqtoken(token[1], "nextminus")) {
5137             _Res_Op_Ctx(token, mpd_next_minus, &ctx);
5138         }
5139         else if (eqtoken(token[1], "nextplus")) {
5140             _Res_Op_Ctx(token, mpd_next_plus, &ctx);
5141         }
5142         else if (eqtoken(token[1], "plus")) {
5143             _Res_Op_Ctx(token, mpd_plus, &ctx);
5144         }
5145         else if (eqtoken(token[1], "reduce")) {
5146             _Res_Op_Ctx(token, mpd_reduce, &ctx);
5147         }
5148         else if (eqtoken(token[1], "squareroot")) {
5149             #ifdef MPD_CONFIG_32
5150                 if (ctx.prec == MPD_MAX_PREC) mpd_set_alloc_limit(16000000);
5151             #endif
5152             _Res_Op_Ctx(token, mpd_sqrt, &ctx);
5153             #ifdef MPD_CONFIG_32
5154                 if (ctx.prec == MPD_MAX_PREC) mpd_set_alloc_limit(SIZE_MAX);
5155             #endif
5156         }
5157         else if (eqtoken(token[1], "quantize_squareroot")) {
5158             #ifdef MPD_CONFIG_32
5159                 if (ctx.prec == MPD_MAX_PREC) mpd_set_alloc_limit(16000000);
5160             #endif
5161             _Res_Op_CtxWithQuantize(token, mpd_sqrt, &ctx);
5162             #ifdef MPD_CONFIG_32
5163                 if (ctx.prec == MPD_MAX_PREC) mpd_set_alloc_limit(SIZE_MAX);
5164             #endif
5165         }
5166         else if (eqtoken(token[1], "tointegral")) {
5167             _Res_Op_Ctx(token, mpd_round_to_int, &ctx);
5168         }
5169         else if (eqtoken(token[1], "tointegralx")) {
5170             _Res_Op_Ctx(token, mpd_round_to_intx, &ctx);
5171         }
5172         else if (eqtoken(token[1], "floor")) {
5173             _Res_Op_Ctx(token, mpd_floor, &ctx);
5174         }
5175         else if (eqtoken(token[1], "ceil")) {
5176             _Res_Op_Ctx(token, mpd_ceil, &ctx);
5177         }
5178         else if (eqtoken(token[1], "trunc")) {
5179             _Res_Op_Ctx(token, mpd_trunc, &ctx);
5180         }
5181 
5182 
5183         /* Binary function returning an int */
5184         else if (eqtoken(token[1], "samequantum")) {
5185             _Int_Binop(token, mpd_same_quantum, &ctx);
5186         }
5187         /* Binary function returning an int, equal operands */
5188         else if (eqtoken(token[1], "samequantum_eq")) {
5189             _Int_EqualBinop(token, mpd_same_quantum, &ctx);
5190         }
5191 
5192         /* Binary functions with mpd_t * result */
5193         else if (eqtoken(token[1], "add")) {
5194             _Res_Binop_Ctx(token, mpd_add, &ctx);
5195         }
5196         else if (eqtoken(token[1], "and")) {
5197             _Res_Binop_Ctx(token, mpd_and, &ctx);
5198         }
5199         else if (eqtoken(token[1], "copysign")) {
5200             _Res_Binop_Ctx(token, mpd_copy_sign, &ctx);
5201         }
5202         else if (eqtoken(token[1], "divide")) {
5203             #ifdef MPD_CONFIG_32
5204                 if (ctx.prec == MPD_MAX_PREC) mpd_set_alloc_limit(16000000);
5205             #endif
5206             _Res_Binop_Ctx(token, mpd_div, &ctx);
5207             #ifdef MPD_CONFIG_32
5208                 if (ctx.prec == MPD_MAX_PREC) mpd_set_alloc_limit(SIZE_MAX);
5209             #endif
5210         }
5211         else if (eqtoken(token[1], "divideint")) {
5212             _Res_Binop_Ctx(token, mpd_divint, &ctx);
5213         }
5214         else if (eqtoken(token[1], "max")) {
5215             _Res_Binop_Ctx(token, mpd_max, &ctx);
5216         }
5217         else if (eqtoken(token[1], "maxmag") || eqtoken(token[1], "max_mag")) {
5218             _Res_Binop_Ctx(token, mpd_max_mag, &ctx);
5219         }
5220         else if (eqtoken(token[1], "min")) {
5221             _Res_Binop_Ctx(token, mpd_min, &ctx);
5222         }
5223         else if (eqtoken(token[1], "minmag") || eqtoken(token[1], "min_mag")) {
5224             _Res_Binop_Ctx(token, mpd_min_mag, &ctx);
5225         }
5226         else if (eqtoken(token[1], "multiply")) {
5227             _Res_Binop_Ctx(token, mpd_mul, &ctx);
5228         }
5229         else if (eqtoken(token[1], "nexttoward")) {
5230             _Res_Binop_Ctx(token, mpd_next_toward, &ctx);
5231         }
5232         else if (eqtoken(token[1], "or")) {
5233             _Res_Binop_Ctx(token, mpd_or, &ctx);
5234         }
5235         else if (eqtoken(token[1], "power")) {
5236             if (extended) {
5237                 ctx.allcr = 0;
5238                 _Res_Binop_Ctx(token, mpd_pow, &ctx);
5239                 ctx.allcr = 1;
5240             }
5241             _Res_Binop_Ctx(token, mpd_pow, &ctx);
5242         }
5243         else if (eqtoken(token[1], "quantize")) {
5244             _Res_Binop_Ctx(token, mpd_quantize, &ctx);
5245         }
5246         else if (eqtoken(token[1], "resc")) {
5247             _Res_Op_Lsize_Ctx(SKIP_NONINT, token, mpd_rescale, &ctx);
5248         }
5249         else if (eqtoken(token[1], "remainder")) {
5250             _Res_Binop_Ctx(token, mpd_rem, &ctx);
5251         }
5252         else if (eqtoken(token[1], "remaindernear")) {
5253             _Res_Binop_Ctx(token, mpd_rem_near, &ctx);
5254         }
5255         else if (eqtoken(token[1], "rotate")) {
5256             _Res_Binop_Ctx(token, mpd_rotate, &ctx);
5257         }
5258         else if (eqtoken(token[1], "scaleb")) {
5259             _Res_Binop_Ctx(token, mpd_scaleb, &ctx);
5260         }
5261         else if (eqtoken(token[1], "shift")) {
5262             _Res_Binop_Ctx(token, mpd_shift, &ctx);
5263             if (extended) {
5264                 _Res_Op_Lsize_Ctx(SKIP_NONINT, token, mpd_shiftn, &ctx);
5265             }
5266         }
5267         else if (eqtoken(token[1], "subtract")) {
5268             _Res_Binop_Ctx(token, mpd_sub, &ctx);
5269         }
5270         else if (eqtoken(token[1], "xor")) {
5271             _Res_Binop_Ctx(token, mpd_xor, &ctx);
5272         }
5273 
5274         /* Binary functions with mpd_t result, equal operands */
5275         else if (eqtoken(token[1], "add_eq")) {
5276             _Res_EqualBinop_Ctx(token, mpd_add, &ctx);
5277         }
5278         else if (eqtoken(token[1], "and_eq")) {
5279             _Res_EqualBinop_Ctx(token, mpd_and, &ctx);
5280         }
5281         else if (eqtoken(token[1], "copysign_eq")) {
5282             _Res_EqualBinop_Ctx(token, mpd_copy_sign, &ctx);
5283         }
5284         else if (eqtoken(token[1], "divide_eq")) {
5285             _Res_EqualBinop_Ctx(token, mpd_div, &ctx);
5286         }
5287         else if (eqtoken(token[1], "divideint_eq")) {
5288             _Res_EqualBinop_Ctx(token, mpd_divint, &ctx);
5289         }
5290         else if (eqtoken(token[1], "max_eq")) {
5291             _Res_EqualBinop_Ctx(token, mpd_max, &ctx);
5292         }
5293         else if (eqtoken(token[1], "maxmag_eq")) {
5294             _Res_EqualBinop_Ctx(token, mpd_max_mag, &ctx);
5295         }
5296         else if (eqtoken(token[1], "min_eq")) {
5297             _Res_EqualBinop_Ctx(token, mpd_min, &ctx);
5298         }
5299         else if (eqtoken(token[1], "minmag_eq")) {
5300             _Res_EqualBinop_Ctx(token, mpd_min_mag, &ctx);
5301         }
5302         else if (eqtoken(token[1], "multiply_eq")) {
5303             _Res_EqualBinop_Ctx(token, mpd_mul, &ctx);
5304         }
5305         else if (eqtoken(token[1], "nexttoward_eq")) {
5306             _Res_EqualBinop_Ctx(token, mpd_next_toward, &ctx);
5307         }
5308         else if (eqtoken(token[1], "or_eq")) {
5309             _Res_EqualBinop_Ctx(token, mpd_or, &ctx);
5310         }
5311         else if (eqtoken(token[1], "power_eq")) {
5312             if (extended) {
5313                 ctx.allcr = 0;
5314                 _Res_EqualBinop_Ctx(token, mpd_pow, &ctx);
5315                 ctx.allcr = 1;
5316             }
5317             _Res_EqualBinop_Ctx(token, mpd_pow, &ctx);
5318         }
5319         else if (eqtoken(token[1], "quantize_eq")) {
5320             _Res_EqualBinop_Ctx(token, mpd_quantize, &ctx);
5321         }
5322         else if (eqtoken(token[1], "remainder_eq")) {
5323             _Res_EqualBinop_Ctx(token, mpd_rem, &ctx);
5324         }
5325         else if (eqtoken(token[1], "remaindernear_eq")) {
5326             _Res_EqualBinop_Ctx(token, mpd_rem_near, &ctx);
5327         }
5328         else if (eqtoken(token[1], "rotate_eq")) {
5329             _Res_EqualBinop_Ctx(token, mpd_rotate, &ctx);
5330         }
5331         else if (eqtoken(token[1], "scaleb_eq")) {
5332             _Res_EqualBinop_Ctx(token, mpd_scaleb, &ctx);
5333         }
5334         else if (eqtoken(token[1], "shift_eq")) {
5335             _Res_EqualBinop_Ctx(token, mpd_shift, &ctx);
5336         }
5337         else if (eqtoken(token[1], "subtract_eq")) {
5338             _Res_EqualBinop_Ctx(token, mpd_sub, &ctx);
5339         }
5340         else if (eqtoken(token[1], "xor_eq")) {
5341             _Res_EqualBinop_Ctx(token, mpd_xor, &ctx);
5342         }
5343 
5344         /* Binary function with binary result */
5345         else if (eqtoken(token[1], "divmod")) {
5346             _Binres_Binop_Ctx(token, mpd_divmod, &ctx);
5347         }
5348 
5349         /* Binary function with binary result, equal operands */
5350         else if (eqtoken(token[1], "divmod_eq")) {
5351             _Binres_EqualBinop_Ctx(token, mpd_divmod, &ctx);
5352         }
5353 
5354 
5355         /* Ternary functions with mpd_t result */
5356         else if (eqtoken(token[1], "fma")) {
5357             _Res_Ternop_Ctx(token, mpd_fma, &ctx);
5358         }
5359         else if (eqtoken(token[1], "powmod")) {
5360             _Res_Ternop_Ctx(token, mpd_powmod, &ctx);
5361         }
5362 
5363         /* Ternary functions with mpd_t result, eq_eq_op */
5364         else if (eqtoken(token[1], "fma_eq_eq_op")) {
5365             _Res_EqEqOp_Ctx(token, mpd_fma, &ctx);
5366         }
5367         else if (eqtoken(token[1], "powmod_eq_eq_op")) {
5368             _Res_EqEqOp_Ctx(token, mpd_powmod, &ctx);
5369         }
5370 
5371         /* Ternary functions with mpd_t result, eq_op_eq */
5372         else if (eqtoken(token[1], "fma_eq_op_eq")) {
5373             _Res_EqOpEq_Ctx(token, mpd_fma, &ctx);
5374         }
5375         else if (eqtoken(token[1], "powmod_eq_op_eq")) {
5376             _Res_EqOpEq_Ctx(token, mpd_powmod, &ctx);
5377         }
5378 
5379         /* Ternary functions with mpd_t result, op_eq_eq */
5380         else if (eqtoken(token[1], "fma_op_eq_eq")) {
5381             _Res_OpEqEq_Ctx(token, mpd_fma, &ctx);
5382         }
5383         else if (eqtoken(token[1], "powmod_op_eq_eq")) {
5384             _Res_OpEqEq_Ctx(token, mpd_powmod, &ctx);
5385         }
5386 
5387         /* Ternary functions with mpd_t result, eq_eq_eq */
5388         else if (eqtoken(token[1], "fma_eq_eq_eq")) {
5389             _Res_EqEqEq_Ctx(token, mpd_fma, &ctx);
5390         }
5391         else if (eqtoken(token[1], "powmod_eq_eq_eq")) {
5392             _Res_EqEqEq_Ctx(token, mpd_powmod, &ctx);
5393         }
5394 
5395         /* Special cases for the comparison functions */
5396         else if (eqtoken(token[1], "compare")) {
5397             _Int_Res_Binop_Ctx(token, mpd_compare, &ctx);
5398             _Int_Binop_Ctx(SKIP_NAN, token, mpd_cmp, &ctx);
5399         }
5400         else if (eqtoken(token[1], "comparesig")) {
5401             _Int_Res_Binop_Ctx(token, mpd_compare_signal, &ctx);
5402         }
5403         else if (eqtoken(token[1], "comparetotal")) {
5404             _Int_Res_Binop(token, mpd_compare_total, &ctx);
5405             _Int_Binop(token, mpd_cmp_total, &ctx);
5406         }
5407         else if (eqtoken(token[1], "comparetotmag")) {
5408             _Int_Res_Binop(token, mpd_compare_total_mag, &ctx);
5409             _Int_Binop(token, mpd_cmp_total_mag, &ctx);
5410         }
5411 
5412         /* Special cases for the comparison functions, equal operands */
5413         else if (eqtoken(token[1], "compare_eq")) {
5414             _Int_Res_EqualBinop_Ctx(token, mpd_compare, &ctx);
5415             _Int_EqualBinop_Ctx(SKIP_NAN, token, mpd_cmp, &ctx);
5416         }
5417         else if (eqtoken(token[1], "comparesig_eq")) {
5418             _Int_Res_EqualBinop_Ctx(token, mpd_compare_signal, &ctx);
5419         }
5420         else if (eqtoken(token[1], "comparetotal_eq")) {
5421             _Int_Res_EqualBinop(token, mpd_compare_total, &ctx);
5422             _Int_EqualBinop(token, mpd_cmp_total, &ctx);
5423         }
5424         else if (eqtoken(token[1], "comparetotmag_eq")) {
5425             _Int_Res_EqualBinop(token, mpd_compare_total_mag, &ctx);
5426             _Int_EqualBinop(token, mpd_cmp_total_mag, &ctx);
5427         }
5428 
5429         /* Special cases for the shift functions */
5430         else if (eqtoken(token[1], "shiftleft")) {
5431             _Res_Op_Lsize_Ctx(SKIP_NONINT, token, _mpd_shiftl, &ctx);
5432         }
5433         else if (eqtoken(token[1], "shiftright")) {
5434             _Res_Op_Lsize_Ctx(SKIP_NONINT, token, _mpd_shiftr, &ctx);
5435         }
5436 
5437         /* Special case for mpd_qln10() */
5438         else if (eqtoken(token[1], "ln10")) {
5439             _test_mpd_qln10(SKIP_NONINT, token, &ctx);
5440         }
5441 
5442         /* Special case for the base conversion functions */
5443         else if (eqtoken(token[1], "baseconv")) {
5444             _Baseconv(token, &ctx);
5445         }
5446 
5447         /* Special cases for the get_int functions */
5448 #ifdef MPD_CONFIG_64
5449         else if (eqtoken(token[1], "get_uint64")) {
5450             _u64_MpdCtx(token, mpd_get_uint, &ctx);
5451         }
5452         else if (eqtoken(token[1], "get_uint64_abs")) {
5453             _u64_MpdCtx(token, mpd_abs_uint, &ctx);
5454         }
5455         else if (eqtoken(token[1], "get_ssize64")) {
5456             _i64_MpdCtx(token, mpd_get_ssize, &ctx);
5457         }
5458 #else
5459         else if (eqtoken(token[1], "get_uint32")) {
5460             _u32_MpdCtx(token, mpd_get_uint, &ctx);
5461         }
5462         else if (eqtoken(token[1], "get_uint32_abs")) {
5463             _u32_MpdCtx(token, mpd_abs_uint, &ctx);
5464         }
5465         else if (eqtoken(token[1], "get_ssize32")) {
5466             _i32_MpdCtx(token, mpd_get_ssize, &ctx);
5467         }
5468 
5469 #endif
5470 
5471 #ifndef MPD_LEGACY_COMPILER
5472         else if (eqtoken(token[1], "get_u64")) {
5473             _u64_MpdCtx(token, mpd_get_u64, &ctx);
5474         }
5475         else if (eqtoken(token[1], "get_i64")) {
5476             _i64_MpdCtx(token, mpd_get_i64, &ctx);
5477         }
5478 #endif
5479 
5480         else if (eqtoken(token[1], "get_u32")) {
5481             _u32_MpdCtx(token, mpd_get_u32, &ctx);
5482         }
5483         else if (eqtoken(token[1], "get_i32")) {
5484             _i32_MpdCtx(token, mpd_get_i32, &ctx);
5485         }
5486 
5487         else if (startswith(token[1], "get_")) {
5488             /* empty */
5489         }
5490 
5491         else if (eqtoken(token[1], "rescale")) {
5492             /* empty */
5493         }
5494 
5495         /* unknown operation */
5496         else {
5497             mpd_err_fatal("%s: unknown operation: %s", filename, line);
5498         }
5499         /* end tests */
5500 
5501         cleanup:
5502         freetoken(token);
5503     }
5504 
5505     mpd_free(line);
5506     mpd_free(tmpline);
5507     if (file != stdin) {
5508         fclose(file);
5509     }
5510 
5511     if (!startswith(filename, "official") &&
5512         !startswith(filename, "additional") &&
5513         !file_failure) {
5514         printf(" PASS\n");
5515     }
5516     else {
5517         printf("\n");
5518     }
5519     fflush(stdout);
5520 }
5521 
5522 static void
traphandler(mpd_context_t * ctx)5523 traphandler(mpd_context_t *ctx)
5524 {
5525     if (ctx->newtrap & MPD_Malloc_error) {
5526         fprintf(stderr, "\n\n\
5527 runtest: out of memory:\n\
5528     - bignum tests require 200MB heap and 300KB stack.\n\
5529     - normal tests require 10MB heap and 50KB stack.\n\n");
5530     }
5531     else {
5532         fprintf(stderr, "\n\nruntest: unexpected error: relevant traps: %u\n\n",
5533                         ctx->newtrap);
5534     }
5535 
5536     exit(1);
5537 }
5538 
5539 static void
usage(void)5540 usage(void)
5541 {
5542     fputs("runtest: usage: runtest testfile [--custom] [--alloc]\n", stderr);
5543     exit(EXIT_FAILURE);
5544 }
5545 
5546 
5547 int
main(int argc,char * argv[])5548 main(int argc, char *argv[])
5549 {
5550     const char *filename = NULL;
5551     bool custom_alloc = false;
5552     bool check_alloc = false;
5553 
5554     for (int i = 1; i < argc; i++) {
5555         if (!filename && (strcmp(argv[i], "-") == 0 || !startswith(argv[i], "--"))) {
5556             filename = argv[i];
5557         }
5558         else if (!custom_alloc && strcmp(argv[i], "--custom") == 0) {
5559             custom_alloc = true;
5560         }
5561         else if (!check_alloc && strcmp(argv[i], "--alloc") == 0) {
5562             check_alloc = true;
5563         }
5564         else {
5565             usage();
5566         }
5567     }
5568     if (filename == NULL) {
5569         usage();
5570     }
5571 
5572     /* Test version */
5573     if (strcmp(mpd_version(), "4.0.0") != (0)) {
5574         fputs("runtest: error: mpd_version() != 4.0.0\n", stderr);
5575         exit(EXIT_FAILURE);
5576     }
5577     if (strcmp(MPD_VERSION, "4.0.0") != (0)) {
5578         fputs("runtest: error: MPD_VERSION != 4.0.0\n", stderr);
5579         exit(EXIT_FAILURE);
5580     }
5581 
5582 #ifdef _MSC_VER
5583   #pragma warning(push)
5584   #pragma warning(disable : 4127)
5585 #endif
5586     if (MPD_MAJOR_VERSION != (4)) {
5587         fputs("runtest: error: MPD_MAJOR_VERSION != 4\n", stderr);
5588         exit(EXIT_FAILURE);
5589     }
5590     if (MPD_MINOR_VERSION != (0)) {
5591         fputs("runtest: error: MPD_MINOR_VERSION != 0\n", stderr);
5592         exit(EXIT_FAILURE);
5593     }
5594     if (MPD_MICRO_VERSION != (0)) {
5595         fputs("runtest: error: MPD_MICRO_VERSION != 0\n", stderr);
5596         exit(EXIT_FAILURE);
5597     }
5598     if (MPD_VERSION_HEX != (0x04000000)) {
5599         fputs("runtest: error: MPD_VERSION_HEX != 0x04000000\n", stderr);
5600         exit(EXIT_FAILURE);
5601     }
5602 #ifdef _MSC_VER
5603   #pragma warning(pop)
5604 #endif
5605 
5606     extended = strcmp(filename, "-") != 0;
5607 
5608     /* Initialize random number generator */
5609     srandom((unsigned int)time(NULL));
5610 
5611     /* Initialize custom allocation functions */
5612     mpd_init_alloc(custom_alloc, check_alloc);
5613 
5614     /* Initialize MPD_MINALLOC (optional, default is 2) */
5615     MPD_MINALLOC = 2;
5616 
5617     /* Initialize trap handler */
5618     mpd_traphandler = traphandler;
5619 
5620     op = mpd_qnew();
5621     op1 = mpd_qnew();
5622     op2 = mpd_qnew();
5623     op3 = mpd_qnew();
5624     tmp = mpd_qnew();
5625     tmp1 = mpd_qnew();
5626     tmp2 = mpd_qnew();
5627     tmp3 = mpd_qnew();
5628     result = mpd_qnew();
5629     result1 = mpd_qnew();
5630     result2 = mpd_qnew();
5631 
5632     triple_cov();
5633     doit(filename);
5634 
5635     mpd_del(op);
5636     mpd_del(op1);
5637     mpd_del(op2);
5638     mpd_del(op3);
5639     mpd_del(tmp);
5640     mpd_del(tmp1);
5641     mpd_del(tmp2);
5642     mpd_del(tmp3);
5643     mpd_del(result);
5644     mpd_del(result1);
5645     mpd_del(result2);
5646 
5647 
5648     return global_failure;
5649 }
5650