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