xref: /llvm-project/polly/lib/External/isl/imath/imdrover.c (revision 658eb9e14264d48888ade0e3daf0b648f76c3f0e)
1 /*
2   Name:     imdrover.c
3   Purpose:  Keeper of the hordes of testing code.
4   Author:   M. J. Fromberger
5 
6   Copyright (C) 2002-2007 Michael J. Fromberger, All Rights Reserved.
7 
8   Permission is hereby granted, free of charge, to any person obtaining a copy
9   of this software and associated documentation files (the "Software"), to deal
10   in the Software without restriction, including without limitation the rights
11   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12   copies of the Software, and to permit persons to whom the Software is
13   furnished to do so, subject to the following conditions:
14 
15   The above copyright notice and this permission notice shall be included in
16   all copies or substantial portions of the Software.
17 
18   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
21   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24   SOFTWARE.
25  */
26 
27 #include <assert.h>
28 #include <limits.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #include "imath.h"
33 #include "imdrover.h"
34 #include "imrat.h"
35 #include "iprime.h"
36 
37 /* Globals visible from outside this file */
38 mp_result imath_errno;
39 char* imath_errmsg;
40 
41 /* Set imath_errno and return failure from a test. */
42 #define FAIL(E) return (imath_errno = (E), false)
43 
44 /* Check that an expression X yields the expected mp_result value V. */
45 #define VCHECK(X, V)           \
46   do {                         \
47     mp_result res_;            \
48     if ((res_ = (X)) != (V)) { \
49       FAIL(res_);              \
50     }                          \
51   } while (0)
52 #define CHECK(X) VCHECK(X, MP_OK)
53 #define ECHECK(X) VCHECK(X, expect)
54 #define ACHECK(X)      \
55   do {                 \
56     if (!(X)) {        \
57       FAIL(MP_BADARG); \
58     }                  \
59   } while (0)
60 
61 #define OUTPUT_LIMIT 2048
62 #define NUM_REGS 16
63 #define OTHER_ERROR -1024
64 
65 static char g_output[OUTPUT_LIMIT];
66 static mpz_t g_zreg[NUM_REGS];
67 static mpq_t g_qreg[NUM_REGS];
68 static unsigned char g_bin1[OUTPUT_LIMIT];
69 static unsigned char g_bin2[OUTPUT_LIMIT];
70 
71 extern void trim_line(char* line); /* borrowed from imtest.c */
72 
73 /* Read in a string with radix tags */
74 static mp_result read_int_value(mp_int z, char* str);
75 static mp_result read_rat_value(mp_rat q, char* str);
76 
77 /* Read in a string with radix tags, as a long (not an mp_int) */
78 static bool read_long(long* z, char* str);
79 
80 /* Parse the input and output values and fill in pointers to the
81    registers containing them.  Returns true if all is well, false
82    in case of error.  Caller allocates in/out to correct sizes. */
83 static bool parse_int_values(testspec_t* t, mp_int* in, mp_int* out,
84                              mp_result* rval);
85 static bool parse_rat_values(testspec_t* t, mp_rat* in, mp_rat* out,
86                              mp_result* rval);
87 
88 /* Parse a result code name and return the corresponding result code */
89 static bool parse_result_code(char* str, mp_result* code);
90 
91 /* Read in a dot-delimited binary sequence to the given buffer, and return the
92    number of bytes read.  Returns < 0 in case of a syntax error.  Records no
93    more than limit bytes. */
94 static int parse_binary(char* str, unsigned char* buf, int limit);
95 
96 /* Clean up registers (called from atexit()) */
97 static void done_testing(void);
98 
99 /*
100  * Utility subroutines for writing tests (explained above)
101  */
102 
read_int_value(mp_int z,char * str)103 static mp_result read_int_value(mp_int z, char* str) {
104   int radix = 10;
105 
106   if (*str == '#') {
107     ++str;
108     switch (*str) {
109       case 'x':
110       case 'X':
111         radix = 16;
112         break;
113       case 'd':
114       case 'D':
115         radix = 10;
116         break;
117       case 'o':
118       case 'O':
119         radix = 8;
120         break;
121       case 'b':
122       case 'B':
123         radix = 2;
124         break;
125       default:
126         return MP_RANGE;
127     }
128     ++str;
129   }
130 
131   return mp_int_read_string(z, radix, str);
132 }
133 
read_rat_value(mp_rat q,char * str)134 static mp_result read_rat_value(mp_rat q, char* str) {
135   int radix = 10;
136 
137   if (*str == '#') {
138     ++str;
139     switch (*str) {
140       case 'x':
141       case 'X':
142         radix = 16;
143         break;
144       case 'd':
145       case 'D':
146         radix = 10;
147         break;
148       case 'o':
149       case 'O':
150         radix = 8;
151         break;
152       case 'b':
153       case 'B':
154         radix = 2;
155         break;
156       default:
157         return MP_RANGE;
158     }
159     ++str;
160   }
161 
162   if (*str == '@')
163     return mp_rat_read_decimal(q, radix, str + 1);
164   else
165     return mp_rat_read_string(q, radix, str);
166 }
167 
read_long(long * z,char * str)168 static bool read_long(long* z, char* str) {
169   char* end;
170   int radix = 10;
171 
172   if (*str == '#') {
173     ++str;
174     switch (*str) {
175       case 'x':
176       case 'X':
177         radix = 16;
178         break;
179       case 'd':
180       case 'D':
181         radix = 10;
182         break;
183       case 'o':
184       case 'O':
185         radix = 8;
186         break;
187       case 'b':
188       case 'B':
189         radix = 2;
190         break;
191       default:
192         return false;
193     }
194     ++str;
195   }
196 
197   *z = strtol(str, &end, radix);
198   return (end != str && *end == '\0');
199 }
200 
parse_int_values(testspec_t * t,mp_int * in,mp_int * out,mp_result * rval)201 static bool parse_int_values(testspec_t* t, mp_int* in, mp_int* out,
202                              mp_result* rval) {
203   int pos = 0;
204   char* str;
205 
206   if (rval != NULL) *rval = MP_OK; /* default */
207 
208   if (in != NULL) {
209     for (int i = 0; i < t->num_inputs; ++i) {
210       str = t->input[i];
211 
212       trim_line(str);
213 
214       if (*str == '=') {
215         int k = abs(atoi(str + 1)) - 1;
216 
217         if (k < 0 || k >= i) {
218           fprintf(stderr, "Line %d: Invalid input back-reference [%s]\n",
219                   t->line, str);
220           return false;
221         }
222 
223         in[i] = in[k];
224       } else {
225         mp_int reg = g_zreg + pos++; /* grab next free register */
226 
227         if (read_int_value(reg, str) != MP_OK) {
228           fprintf(stderr, "Line %d: Invalid input value [%s]\n", t->line, str);
229           return false;
230         }
231 
232         in[i] = reg;
233       }
234     }
235   }
236 
237   for (int i = 0; i < t->num_outputs; ++i) {
238     mp_int reg = g_zreg + pos++;
239 
240     str = t->output[i];
241 
242     trim_line(str);
243 
244     if (strcmp(str, "?") == 0)
245       mp_int_zero(reg);
246     else if (*str == '$') {
247       mp_result code;
248 
249       if (!parse_result_code(str, &code)) {
250         fprintf(stderr, "Line %d: Invalid result code [%s]\n", t->line, str);
251         return false;
252       } else if (rval == NULL) {
253         fprintf(stderr, "Line %d: Result code not permitted here [%s]\n",
254                 t->line, str);
255         return false;
256       } else
257         *rval = code;
258 
259       /* Provide a dummy value for the corresponding output */
260       mp_int_zero(reg);
261     } else if (out != NULL && read_int_value(reg, str) != MP_OK) {
262       fprintf(stderr, "Line %d: Invalid output value [%s]\n", t->line, str);
263       return false;
264     }
265 
266     if (out != NULL) out[i] = reg;
267   }
268 
269   return true;
270 }
271 
parse_rat_values(testspec_t * t,mp_rat * in,mp_rat * out,mp_result * rval)272 static bool parse_rat_values(testspec_t* t, mp_rat* in, mp_rat* out,
273                              mp_result* rval) {
274   int pos = 0;
275   char* str;
276 
277   if (rval != NULL) *rval = MP_OK; /* default */
278 
279   if (in != NULL) {
280     for (int i = 0; i < t->num_inputs; ++i) {
281       str = t->input[i];
282 
283       trim_line(str);
284 
285       if (*str == '=') {
286         int k = abs(atoi(str + 1)) - 1;
287 
288         if (k < 0 || k >= i) {
289           fprintf(stderr, "Line %d: Invalid input back-reference [%s]\n",
290                   t->line, str);
291           return false;
292         }
293 
294         in[i] = in[k];
295       } else {
296         mp_rat reg = g_qreg + pos++; /* grab next free register */
297 
298         if (read_rat_value(reg, str) != MP_OK) {
299           fprintf(stderr, "Line %d: Invalid input value [%s]\n", t->line, str);
300           return false;
301         }
302 
303         in[i] = reg;
304       }
305     }
306   }
307 
308   for (int i = 0; i < t->num_outputs; ++i) {
309     mp_rat reg = g_qreg + pos++;
310 
311     str = t->output[i];
312 
313     trim_line(str);
314 
315     if (strcmp(str, "?") == 0)
316       mp_rat_zero(reg);
317     else if (*str == '$') {
318       mp_result code;
319 
320       if (!parse_result_code(str, &code)) {
321         fprintf(stderr, "Line %d: Invalid result code [%s]\n", t->line, str);
322         return false;
323       } else if (rval == NULL) {
324         fprintf(stderr, "Line %d: Result code not permitted here [%s]\n",
325                 t->line, str);
326         return false;
327       } else
328         *rval = code;
329 
330       /* Provide a dummy value for the corresponding output */
331       mp_rat_zero(reg);
332     } else if (out != NULL && read_rat_value(reg, str) != MP_OK) {
333       fprintf(stderr, "Line %d: Invalid output value [%s]\n", t->line, str);
334       return false;
335     }
336 
337     if (out != NULL) out[i] = reg;
338   }
339 
340   return true;
341 }
342 
parse_result_code(char * str,mp_result * code)343 static bool parse_result_code(char* str, mp_result* code) {
344   if (str[0] == '$') {
345     if (str[1] == '#') {
346       long v;
347 
348       if (!read_long(&v, str + 2)) return false;
349 
350       *code = (mp_result)v;
351     } else if (strcmp(str + 1, "MP_OK") == 0 ||
352                strcmp(str + 1, "MP_FALSE") == 0) {
353       *code = MP_OK;
354     } else if (strcmp(str + 1, "MP_TRUE") == 0) {
355       *code = MP_TRUE;
356     } else if (strcmp(str + 1, "MP_MEMORY") == 0) {
357       *code = MP_MEMORY;
358     } else if (strcmp(str + 1, "MP_RANGE") == 0) {
359       *code = MP_RANGE;
360     } else if (strcmp(str + 1, "MP_UNDEF") == 0) {
361       *code = MP_UNDEF;
362     } else if (strcmp(str + 1, "MP_TRUNC") == 0) {
363       *code = MP_TRUNC;
364     } else if (strcmp(str + 1, "MP_ROUND_UP") == 0) {
365       *code = MP_ROUND_UP;
366     } else if (strcmp(str + 1, "MP_ROUND_DOWN") == 0) {
367       *code = MP_ROUND_DOWN;
368     } else if (strcmp(str + 1, "MP_ROUND_HALF_UP") == 0) {
369       *code = MP_ROUND_HALF_UP;
370     } else if (strcmp(str + 1, "MP_ROUND_HALF_DOWN") == 0) {
371       *code = MP_ROUND_HALF_DOWN;
372     } else {
373       return false;
374     }
375   }
376 
377   return true;
378 }
379 
parse_binary(char * str,unsigned char * buf,int limit)380 static int parse_binary(char* str, unsigned char* buf, int limit) {
381   int pos = 0;
382   char* tok;
383 
384   trim_line(str);
385 
386   for (tok = strtok(str, "."); tok != NULL && pos < limit;
387        tok = strtok(NULL, ".")) {
388     long v;
389 
390     if (!read_long(&v, tok) || v > UCHAR_MAX || v < 0) return -1;
391 
392     buf[pos++] = (unsigned char)v;
393   }
394 
395   return pos;
396 }
397 
done_testing(void)398 static void done_testing(void) {
399   int i;
400 
401   for (i = 0; i < NUM_REGS; ++i) {
402     mp_int_clear(g_zreg + i);
403     mp_rat_clear(g_qreg + i);
404   }
405 }
406 
407 /*
408  * Global functions visible to callers outside this file.
409  */
410 
init_testing(void)411 void init_testing(void) {
412   static int is_done = 0;
413 
414   if (is_done) return;
415 
416   for (int i = 0; i < NUM_REGS; ++i) {
417     assert(mp_int_init(g_zreg + i) == MP_OK);
418     assert(mp_rat_init(g_qreg + i) == MP_OK);
419   }
420 
421   imath_errmsg = g_output;
422 
423   assert(atexit(done_testing) == 0);
424   is_done = 1;
425 }
426 
reset_registers(void)427 void reset_registers(void) {
428   for (int i = 0; i < NUM_REGS; ++i) {
429     mp_int_zero(g_zreg + i);
430     mp_rat_zero(g_qreg + i);
431   }
432 }
433 
test_init(testspec_t * t,FILE * ofp)434 bool test_init(testspec_t* t, FILE* ofp) {
435   mp_int in[2], out[1];
436   mp_small v;
437   mp_usmall uv;
438   mp_result expect;
439 
440   ACHECK(parse_int_values(t, in, out, &expect));
441 
442   if (strcmp(t->code, "initu") == 0) {
443     CHECK(mp_int_to_uint(in[1], &uv));
444     ECHECK(mp_int_init_uvalue(in[0], uv));
445   } else { /* initv */
446     CHECK(mp_int_to_int(in[1], &v));
447     ECHECK(mp_int_init_value(in[0], v));
448   }
449 
450   if (expect == MP_OK && mp_int_compare(in[0], out[0]) != 0) {
451     mp_int_to_string(in[0], 10, g_output, OUTPUT_LIMIT);
452     FAIL(OTHER_ERROR);
453   }
454 
455   return true;
456 }
457 
test_set(testspec_t * t,FILE * ofp)458 bool test_set(testspec_t* t, FILE* ofp) {
459   mp_int in[2], out[1];
460   mp_small v;
461   mp_usmall uv;
462   mp_result expect;
463 
464   ACHECK(parse_int_values(t, in, out, &expect));
465 
466   if (strcmp(t->code, "setu") == 0) {
467     CHECK(mp_int_to_uint(in[1], &uv));
468     ECHECK(mp_int_set_uvalue(in[0], uv));
469   } else { /* setv */
470     CHECK(mp_int_to_int(in[1], &v));
471     ECHECK(mp_int_set_value(in[0], v));
472   }
473 
474   if (expect == MP_OK && mp_int_compare(in[0], out[0]) != 0) {
475     mp_int_to_string(in[0], 10, g_output, OUTPUT_LIMIT);
476     FAIL(OTHER_ERROR);
477   }
478 
479   return true;
480 }
481 
test_neg(testspec_t * t,FILE * ofp)482 bool test_neg(testspec_t* t, FILE* ofp) {
483   mp_int in[2], out[1];
484   mp_result expect;
485 
486   ACHECK(parse_int_values(t, in, out, &expect));
487   ECHECK(mp_int_neg(in[0], in[1]));
488 
489   if (expect == MP_OK && mp_int_compare(in[1], out[0]) != 0) {
490     mp_int_to_string(in[1], 10, g_output, OUTPUT_LIMIT);
491     FAIL(OTHER_ERROR);
492   }
493 
494   return true;
495 }
496 
test_abs(testspec_t * t,FILE * ofp)497 bool test_abs(testspec_t* t, FILE* ofp) {
498   mp_int in[2], out[1];
499   mp_result expect;
500 
501   ACHECK(parse_int_values(t, in, out, &expect));
502   ECHECK(mp_int_abs(in[0], in[1]));
503 
504   if (expect == MP_OK && mp_int_compare(in[1], out[0]) != 0) {
505     mp_int_to_string(in[1], 10, g_output, OUTPUT_LIMIT);
506     FAIL(OTHER_ERROR);
507   }
508 
509   return true;
510 }
511 
test_add(testspec_t * t,FILE * ofp)512 bool test_add(testspec_t* t, FILE* ofp) {
513   mp_int in[3], out[1];
514   mp_small v;
515   mp_result expect;
516 
517   ACHECK(parse_int_values(t, in, out, &expect));
518 
519   if (strcmp(t->code, "addv") == 0) {
520     CHECK(mp_int_to_int(in[1], &v));
521     ECHECK(mp_int_add_value(in[0], v, in[2]));
522   } else {
523     ECHECK(mp_int_add(in[0], in[1], in[2]));
524   }
525 
526   if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
527     mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
528     FAIL(OTHER_ERROR);
529   }
530 
531   return true;
532 }
533 
test_sub(testspec_t * t,FILE * ofp)534 bool test_sub(testspec_t* t, FILE* ofp) {
535   mp_int in[3], out[1];
536   mp_small v;
537   mp_result expect;
538 
539   ACHECK(parse_int_values(t, in, out, &expect));
540 
541   if (strcmp(t->code, "subv") == 0) {
542     CHECK(mp_int_to_int(in[1], &v));
543     ECHECK(mp_int_sub_value(in[0], v, in[2]));
544   } else {
545     ECHECK(mp_int_sub(in[0], in[1], in[2]));
546   }
547 
548   if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
549     mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
550     FAIL(OTHER_ERROR);
551   }
552   return true;
553 }
554 
test_mul(testspec_t * t,FILE * ofp)555 bool test_mul(testspec_t* t, FILE* ofp) {
556   mp_int in[3], out[1];
557   mp_result expect;
558 
559   ACHECK(parse_int_values(t, in, out, &expect));
560   ECHECK(mp_int_mul(in[0], in[1], in[2]));
561 
562   if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
563     mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
564     FAIL(OTHER_ERROR);
565   }
566   return true;
567 }
568 
test_mulp2(testspec_t * t,FILE * ofp)569 bool test_mulp2(testspec_t* t, FILE* ofp) {
570   mp_int in[3], out[1];
571   mp_result expect;
572   mp_small p2;
573 
574   ACHECK(parse_int_values(t, in, out, &expect));
575   CHECK(mp_int_to_int(in[1], &p2));
576   ECHECK(mp_int_mul_pow2(in[0], p2, in[2]));
577 
578   if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
579     mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
580     FAIL(OTHER_ERROR);
581   }
582   return true;
583 }
584 
test_mulv(testspec_t * t,FILE * ofp)585 bool test_mulv(testspec_t* t, FILE* ofp) {
586   mp_int in[3], out[1];
587   mp_result expect;
588   mp_small v;
589 
590   ACHECK(parse_int_values(t, in, out, &expect));
591   CHECK(mp_int_to_int(in[1], &v));
592   ECHECK(mp_int_mul_value(in[0], v, in[2]));
593 
594   if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
595     mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
596     FAIL(OTHER_ERROR);
597   }
598   return true;
599 }
600 
test_sqr(testspec_t * t,FILE * ofp)601 bool test_sqr(testspec_t* t, FILE* ofp) {
602   mp_int in[2], out[1];
603   mp_result expect;
604 
605   ACHECK(parse_int_values(t, in, out, &expect));
606   ECHECK(mp_int_sqr(in[0], in[1]));
607 
608   if (expect == MP_OK && mp_int_compare(in[1], out[0]) != 0) {
609     mp_int_to_string(in[1], 10, g_output, OUTPUT_LIMIT);
610     FAIL(OTHER_ERROR);
611   }
612   return true;
613 }
614 
test_div(testspec_t * t,FILE * ofp)615 bool test_div(testspec_t* t, FILE* ofp) {
616   mp_int in[4], out[2];
617   mp_result expect;
618 
619   ACHECK(parse_int_values(t, in, out, &expect));
620   ECHECK(mp_int_div(in[0], in[1], in[2], in[3]));
621 
622   if (expect == MP_OK && ((mp_int_compare(in[2], out[0]) != 0) ||
623                           (mp_int_compare(in[3], out[1]) != 0))) {
624     int len;
625     char* str;
626 
627     mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
628     str = g_output + (len = strlen(g_output));
629     *str++ = ',';
630     mp_int_to_string(in[3], 10, str, OUTPUT_LIMIT - (len + 1));
631     FAIL(OTHER_ERROR);
632   }
633   return true;
634 }
635 
test_divp2(testspec_t * t,FILE * ofp)636 bool test_divp2(testspec_t* t, FILE* ofp) {
637   mp_int in[4], out[2];
638   mp_result expect;
639   mp_small p2;
640 
641   ACHECK(parse_int_values(t, in, out, &expect));
642   CHECK(mp_int_to_int(in[1], &p2));
643   ECHECK(mp_int_div_pow2(in[0], p2, in[2], in[3]));
644 
645   if (expect == MP_OK && ((mp_int_compare(in[2], out[0]) != 0) ||
646                           (mp_int_compare(in[3], out[1]) != 0))) {
647     int len;
648     char* str;
649 
650     mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
651     str = g_output + (len = strlen(g_output));
652     *str++ = ',';
653     mp_int_to_string(in[3], 10, str, OUTPUT_LIMIT - (len + 1));
654     FAIL(OTHER_ERROR);
655   }
656   return true;
657 }
658 
test_divv(testspec_t * t,FILE * ofp)659 bool test_divv(testspec_t* t, FILE* ofp) {
660   mp_int in[3], out[2];
661   mp_result expect;
662   mp_small v, rem, orem;
663 
664   ACHECK(parse_int_values(t, in, out, &expect));
665   CHECK(mp_int_to_int(in[1], &v));
666   CHECK(mp_int_to_int(out[1], &orem));
667   ECHECK(mp_int_div_value(in[0], v, in[2], &rem));
668 
669   if (expect == MP_OK &&
670       ((mp_int_compare(in[2], out[0]) != 0) || (rem != orem))) {
671     char* str;
672 
673     mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
674     str = g_output + strlen(g_output);
675     *str++ = ',';
676     sprintf(str, "%ld", rem);
677     FAIL(OTHER_ERROR);
678   }
679   return true;
680 }
681 
test_expt(testspec_t * t,FILE * ofp)682 bool test_expt(testspec_t* t, FILE* ofp) {
683   mp_int in[3], out[1];
684   mp_result expect;
685   mp_small pow;
686 
687   ACHECK(parse_int_values(t, in, out, &expect));
688   CHECK(mp_int_to_int(in[1], &pow));
689   ECHECK(mp_int_expt(in[0], pow, in[2]));
690 
691   if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
692     mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
693     FAIL(OTHER_ERROR);
694   }
695   return true;
696 }
697 
test_exptv(testspec_t * t,FILE * ofp)698 bool test_exptv(testspec_t* t, FILE* ofp) {
699   mp_int in[3], out[1];
700   mp_result expect;
701   mp_small a, b;
702 
703   ACHECK(parse_int_values(t, in, out, &expect));
704   CHECK(mp_int_to_int(in[0], &a));
705   CHECK(mp_int_to_int(in[1], &b));
706   ECHECK(mp_int_expt_value(a, b, in[2]));
707 
708   if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
709     mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
710     FAIL(OTHER_ERROR);
711   }
712   return true;
713 }
714 
test_exptf(testspec_t * t,FILE * ofp)715 bool test_exptf(testspec_t* t, FILE* ofp) {
716   mp_int in[3], out[1];
717   mp_result expect;
718 
719   ACHECK(parse_int_values(t, in, out, &expect));
720   ECHECK(mp_int_expt_full(in[0], in[1], in[2]));
721 
722   if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
723     mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
724     FAIL(OTHER_ERROR);
725   }
726   return true;
727 }
728 
test_mod(testspec_t * t,FILE * ofp)729 bool test_mod(testspec_t* t, FILE* ofp) {
730   mp_int in[3], out[1];
731   mp_result expect;
732 
733   ACHECK(parse_int_values(t, in, out, &expect));
734   ECHECK(mp_int_mod(in[0], in[1], in[2]));
735 
736   if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
737     mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
738     FAIL(OTHER_ERROR);
739   }
740   return true;
741 }
742 
test_gcd(testspec_t * t,FILE * ofp)743 bool test_gcd(testspec_t* t, FILE* ofp) {
744   mp_int in[3], out[1];
745   mp_result expect;
746 
747   ACHECK(parse_int_values(t, in, out, &expect));
748   ECHECK(mp_int_gcd(in[0], in[1], in[2]));
749 
750   if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
751     mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
752     FAIL(OTHER_ERROR);
753   }
754   return true;
755 }
756 
test_egcd(testspec_t * t,FILE * ofp)757 bool test_egcd(testspec_t* t, FILE* ofp) {
758   mp_int in[5], out[3], t1 = g_zreg + 8, t2 = g_zreg + 9;
759   mp_result expect;
760 
761   ACHECK(parse_int_values(t, in, out, &expect));
762   ECHECK(mp_int_egcd(in[0], in[1], in[2], in[3], in[4]));
763 
764   /* If we got an error we expected, return success immediately */
765   if (expect != MP_OK) return true;
766 
767   if ((mp_int_compare(in[2], out[0]) != 0) ||
768       (mp_int_compare(in[3], out[1]) != 0) ||
769       (mp_int_compare(in[4], out[2]) != 0)) {
770     int len, len2;
771     char* str;
772 
773     /* Failure might occur because the tester computed x and y in a different
774        way than we did.  Verify that the results are correct before reporting
775        an error. */
776     mp_int_mul(in[3], in[0], t1);
777     mp_int_mul(in[4], in[1], t2);
778     mp_int_add(t1, t2, t2);
779     if (mp_int_compare(t2, in[2]) == 0) return true;
780 
781     mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
782     str = g_output + (len = strlen(g_output));
783     *str++ = ',';
784     mp_int_to_string(in[3], 10, str, OUTPUT_LIMIT - (len + 1));
785     str = str + (len2 = strlen(str));
786     *str++ = ',';
787     mp_int_to_string(in[4], 10, str, OUTPUT_LIMIT - (len + len2 + 2));
788     FAIL(OTHER_ERROR);
789   }
790   return true;
791 }
792 
test_lcm(testspec_t * t,FILE * ofp)793 bool test_lcm(testspec_t* t, FILE* ofp) {
794   mp_int in[3], out[1];
795   mp_result expect;
796 
797   ACHECK(parse_int_values(t, in, out, &expect));
798   ECHECK(mp_int_lcm(in[0], in[1], in[2]));
799 
800   if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
801     mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
802     FAIL(OTHER_ERROR);
803   }
804   return true;
805 }
806 
test_sqrt(testspec_t * t,FILE * ofp)807 bool test_sqrt(testspec_t* t, FILE* ofp) {
808   mp_int in[2], out[1];
809   mp_result expect;
810 
811   ACHECK(parse_int_values(t, in, out, &expect));
812   ECHECK(mp_int_sqrt(in[0], in[1]));
813 
814   if (expect == MP_OK && mp_int_compare(in[1], out[0]) != 0) {
815     mp_int_to_string(in[1], 10, g_output, OUTPUT_LIMIT);
816     FAIL(OTHER_ERROR);
817   }
818   return true;
819 }
820 
test_root(testspec_t * t,FILE * ofp)821 bool test_root(testspec_t* t, FILE* ofp) {
822   mp_int in[3], out[1];
823   mp_small v;
824   mp_result expect;
825 
826   ACHECK(parse_int_values(t, in, out, &expect));
827   CHECK(mp_int_to_int(in[1], &v));
828   ECHECK(mp_int_root(in[0], v, in[2]));
829 
830   if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
831     mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
832     FAIL(OTHER_ERROR);
833   }
834   return true;
835 }
836 
test_invmod(testspec_t * t,FILE * ofp)837 bool test_invmod(testspec_t* t, FILE* ofp) {
838   mp_int in[3], out[1];
839   mp_result expect;
840 
841   ACHECK(parse_int_values(t, in, out, &expect));
842   ECHECK(mp_int_invmod(in[0], in[1], in[2]));
843 
844   if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
845     mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
846     FAIL(OTHER_ERROR);
847   }
848   return true;
849 }
850 
test_exptmod(testspec_t * t,FILE * ofp)851 bool test_exptmod(testspec_t* t, FILE* ofp) {
852   mp_int in[4], out[1];
853   mp_result expect;
854 
855   ACHECK(parse_int_values(t, in, out, &expect));
856   ECHECK(mp_int_exptmod(in[0], in[1], in[2], in[3]));
857 
858   if (expect == MP_OK && mp_int_compare(in[3], out[0]) != 0) {
859     mp_int_to_string(in[3], 10, g_output, OUTPUT_LIMIT);
860     FAIL(OTHER_ERROR);
861   }
862   return true;
863 }
864 
test_exptmod_ev(testspec_t * t,FILE * ofp)865 bool test_exptmod_ev(testspec_t* t, FILE* ofp) {
866   mp_int in[4], out[1];
867   mp_result expect;
868   mp_small v;
869 
870   ACHECK(parse_int_values(t, in, out, &expect));
871   CHECK(mp_int_to_int(in[1], &v));
872   ECHECK(mp_int_exptmod_evalue(in[0], v, in[2], in[3]));
873 
874   if (expect == MP_OK && mp_int_compare(in[3], out[0]) != 0) {
875     mp_int_to_string(in[3], 10, g_output, OUTPUT_LIMIT);
876     FAIL(OTHER_ERROR);
877   }
878   return true;
879 }
880 
test_exptmod_bv(testspec_t * t,FILE * ofp)881 bool test_exptmod_bv(testspec_t* t, FILE* ofp) {
882   mp_int in[4], out[1];
883   mp_result expect;
884   mp_small v;
885 
886   ACHECK(parse_int_values(t, in, out, &expect));
887   CHECK(mp_int_to_int(in[0], &v));
888   ECHECK(mp_int_exptmod_bvalue(v, in[1], in[2], in[3]));
889 
890   if (expect == MP_OK && mp_int_compare(in[3], out[0]) != 0) {
891     mp_int_to_string(in[3], 10, g_output, OUTPUT_LIMIT);
892     FAIL(OTHER_ERROR);
893   }
894   return true;
895 }
896 
test_comp(testspec_t * t,FILE * ofp)897 bool test_comp(testspec_t* t, FILE* ofp) {
898   mp_int in[2];
899   mp_result res, expect;
900 
901   ACHECK(parse_int_values(t, in, NULL, &expect));
902 
903   if ((res = mp_int_compare(in[0], in[1])) != expect) {
904     sprintf(g_output, "Incorrect comparison result (want %d, got %d)", expect,
905             res);
906     FAIL(OTHER_ERROR);
907   }
908   return true;
909 }
910 
test_ucomp(testspec_t * t,FILE * ofp)911 bool test_ucomp(testspec_t* t, FILE* ofp) {
912   mp_int in[2];
913   mp_result res, expect;
914 
915   ACHECK(parse_int_values(t, in, NULL, &expect));
916 
917   if ((res = mp_int_compare_unsigned(in[0], in[1])) != expect) {
918     sprintf(g_output, "Incorrect comparison result (want %d, got %d)", expect,
919             res);
920     FAIL(OTHER_ERROR);
921   }
922   return true;
923 }
924 
test_zcomp(testspec_t * t,FILE * ofp)925 bool test_zcomp(testspec_t* t, FILE* ofp) {
926   mp_int in[1];
927   mp_result res, expect;
928 
929   ACHECK(parse_int_values(t, in, NULL, &expect));
930 
931   if ((res = mp_int_compare_zero(in[0])) != expect) {
932     sprintf(g_output, "Incorrect comparison result (want %d, got %d)", expect,
933             res);
934     FAIL(OTHER_ERROR);
935   }
936   return true;
937 }
938 
test_vcomp(testspec_t * t,FILE * ofp)939 bool test_vcomp(testspec_t* t, FILE* ofp) {
940   mp_int in[2];
941   mp_result res, expect;
942   mp_small v;
943 
944   ACHECK(parse_int_values(t, in, NULL, &expect));
945 
946   v = atoi(t->input[1]);
947   if ((res = mp_int_compare_value(in[0], v)) != expect) {
948     sprintf(g_output, "Incorrect comparison result (want %d, got %d)", expect,
949             res);
950     FAIL(OTHER_ERROR);
951   }
952   return true;
953 }
954 
test_uvcomp(testspec_t * t,FILE * ofp)955 bool test_uvcomp(testspec_t* t, FILE* ofp) {
956   mp_int in[2];
957   mp_result res, expect;
958   mp_usmall v;
959 
960   ACHECK(parse_int_values(t, in, NULL, &expect));
961 
962   v = strtoul(t->input[1], NULL, 0);
963   if ((res = mp_int_compare_uvalue(in[0], v)) != expect) {
964     sprintf(g_output, "Incorrect comparison result (want %d, got %d)", expect,
965             res);
966     FAIL(OTHER_ERROR);
967   }
968   return true;
969 }
970 
test_tostr(testspec_t * t,FILE * ofp)971 bool test_tostr(testspec_t* t, FILE* ofp) {
972   mp_int in[2];
973   mp_small radix;
974   mp_result len;
975 
976   ACHECK(parse_int_values(t, in, NULL, NULL));
977   ACHECK(mp_int_to_int(in[1], &radix) == MP_OK);
978 
979   if (radix < MP_MIN_RADIX || radix > MP_MAX_RADIX) FAIL(MP_RANGE);
980 
981   trim_line(t->output[0]);
982   len = mp_int_string_len(in[0], radix);
983 
984   CHECK(mp_int_to_string(in[0], radix, g_output, len));
985 
986   if (strcmp(t->output[0], g_output) != 0) FAIL(OTHER_ERROR);
987 
988   return true;
989 }
990 
test_tobin(testspec_t * t,FILE * ofp)991 bool test_tobin(testspec_t* t, FILE* ofp) {
992   mp_int in[1];
993   int test_len, out_len;
994 
995   ACHECK(parse_int_values(t, in, NULL, NULL));
996 
997   trim_line(t->output[0]);
998   if ((out_len = parse_binary(t->output[0], g_bin1, sizeof(g_bin1))) < 0)
999     FAIL(MP_BADARG);
1000 
1001   if ((test_len = mp_int_binary_len(in[0])) != out_len) {
1002     sprintf(g_output, "Output lengths do not match (want %d, got %d)", test_len,
1003             out_len);
1004     FAIL(OTHER_ERROR);
1005   }
1006 
1007   CHECK(mp_int_to_binary(in[0], g_bin2, sizeof(g_bin2)));
1008 
1009   if (memcmp(g_bin1, g_bin2, test_len) != 0) {
1010     int pos = 0, i;
1011 
1012     for (i = 0; i < test_len - 1; ++i)
1013       pos += sprintf(g_output + pos, "%d.", g_bin2[i]);
1014 
1015     sprintf(g_output + pos, "%d", g_bin2[i]);
1016     FAIL(OTHER_ERROR);
1017   }
1018   return true;
1019 }
1020 
test_to_int(testspec_t * t,FILE * ofp)1021 bool test_to_int(testspec_t* t, FILE* ofp) {
1022   mp_int in[1], out[1];
1023   mp_small v;
1024   mp_result expect;
1025 
1026   ACHECK(parse_int_values(t, in, out, &expect));
1027   ECHECK(mp_int_to_int(in[0], &v));
1028 
1029   if (expect == MP_OK && mp_int_compare_value(out[0], v) != 0) {
1030     sprintf(g_output, "Incorrect value (got %ld)", v);
1031     FAIL(OTHER_ERROR);
1032   }
1033   return true;
1034 }
1035 
test_to_uint(testspec_t * t,FILE * ofp)1036 bool test_to_uint(testspec_t* t, FILE* ofp) {
1037   mp_int in[1], out[1];
1038   mp_usmall v;
1039   mp_result expect;
1040 
1041   ACHECK(parse_int_values(t, in, out, &expect));
1042   ECHECK(mp_int_to_uint(in[0], &v));
1043 
1044   if (expect == MP_OK && mp_int_compare_uvalue(out[0], v) != 0) {
1045     sprintf(g_output, "Incorrect value (got %lu)", v);
1046     FAIL(OTHER_ERROR);
1047   }
1048   return true;
1049 }
1050 
test_read_binary(testspec_t * t,FILE * ofp)1051 bool test_read_binary(testspec_t* t, FILE* ofp) {
1052   mp_int out[1], in = g_zreg + 1;
1053   int in_len;
1054   mp_result expect;
1055 
1056   ACHECK(parse_int_values(t, NULL, out, &expect));
1057 
1058   trim_line(t->input[0]);
1059   if ((in_len = parse_binary(t->input[0], g_bin1, sizeof(g_bin1))) < 0)
1060     FAIL(MP_BADARG);
1061 
1062   ECHECK(mp_int_read_binary(in, g_bin1, in_len));
1063 
1064   if (expect == MP_OK && mp_int_compare(in, out[0]) != 0) {
1065     mp_int_to_string(in, 10, g_output, OUTPUT_LIMIT);
1066     FAIL(OTHER_ERROR);
1067   }
1068   return true;
1069 }
1070 
test_to_uns(testspec_t * t,FILE * ofp)1071 bool test_to_uns(testspec_t* t, FILE* ofp) {
1072   mp_int in[1];
1073   int test_len, out_len;
1074 
1075   ACHECK(parse_int_values(t, in, NULL, NULL));
1076 
1077   trim_line(t->output[0]);
1078   if ((out_len = parse_binary(t->output[0], g_bin1, sizeof(g_bin1))) < 0)
1079     FAIL(MP_BADARG);
1080 
1081   if ((test_len = mp_int_unsigned_len(in[0])) != out_len) {
1082     sprintf(g_output, "Output lengths do not match (want %d, got %d)", test_len,
1083             out_len);
1084     FAIL(OTHER_ERROR);
1085   }
1086 
1087   CHECK(mp_int_to_unsigned(in[0], g_bin2, sizeof(g_bin2)));
1088 
1089   if (memcmp(g_bin1, g_bin2, test_len) != 0) {
1090     int pos = 0, i;
1091 
1092     for (i = 0; i < test_len - 1; ++i)
1093       pos += sprintf(g_output + pos, "%d.", g_bin2[i]);
1094 
1095     sprintf(g_output + pos, "%d", g_bin2[i]);
1096     FAIL(OTHER_ERROR);
1097   }
1098   return true;
1099 }
1100 
test_read_uns(testspec_t * t,FILE * ofp)1101 bool test_read_uns(testspec_t* t, FILE* ofp) {
1102   mp_int out[1], in = g_zreg + 1;
1103   int in_len;
1104   mp_result expect;
1105 
1106   ACHECK(parse_int_values(t, NULL, out, &expect));
1107 
1108   trim_line(t->input[0]);
1109   if ((in_len = parse_binary(t->input[0], g_bin1, sizeof(g_bin1))) < 0)
1110     FAIL(MP_BADARG);
1111 
1112   ECHECK(mp_int_read_unsigned(in, g_bin1, in_len));
1113 
1114   if (expect == MP_OK && mp_int_compare(in, out[0]) != 0) {
1115     mp_int_to_string(in, 10, g_output, OUTPUT_LIMIT);
1116     FAIL(OTHER_ERROR);
1117   }
1118   return true;
1119 }
1120 
test_meta(testspec_t * t,FILE * ofp)1121 bool test_meta(testspec_t* t, FILE* ofp) {
1122   mp_int *in = NULL, *out = NULL;
1123   int i, j;
1124   mp_result expect;
1125 
1126   if (t->num_inputs > 0) {
1127     in = calloc(t->num_inputs, sizeof(mp_int));
1128   }
1129   if (t->num_outputs > 0) {
1130     out = calloc(t->num_outputs, sizeof(mp_int));
1131   }
1132 
1133   if (!parse_int_values(t, in, out, &expect)) {
1134     if (in != NULL) free(in);
1135     if (out != NULL) free(out);
1136     FAIL(MP_BADARG);
1137   }
1138 
1139   fprintf(ofp, "Test '%s' defined at line %d\n", t->code, t->line);
1140   fprintf(ofp, "Expected result: %d\n", expect);
1141   fprintf(ofp, "Input values: %d\n", t->num_inputs);
1142   for (i = 0; i < t->num_inputs; ++i) {
1143     mp_int_to_string(in[i], 10, g_output, OUTPUT_LIMIT);
1144 
1145     fprintf(ofp, " %2d.) %s", i + 1, g_output);
1146 
1147     for (j = i - 1; j >= 0; --j)
1148       if (in[j] == in[i]) {
1149         fprintf(ofp, " (=> %d)", j + 1);
1150         break;
1151       }
1152 
1153     fputc('\n', ofp);
1154   }
1155   fprintf(ofp, "Output values: %d\n", t->num_outputs);
1156   for (i = 0; i < t->num_outputs; ++i) {
1157     mp_int_to_string(out[i], 10, g_output, OUTPUT_LIMIT);
1158 
1159     fprintf(ofp, " %2d.) %s\n", i + 1, g_output);
1160   }
1161   if (in != NULL) free(in);
1162   if (out != NULL) free(out);
1163   return true;
1164 }
1165 
test_qneg(testspec_t * t,FILE * ofp)1166 bool test_qneg(testspec_t* t, FILE* ofp) {
1167   mp_rat in[2], out[1];
1168   mp_result expect;
1169 
1170   ACHECK(parse_rat_values(t, in, out, &expect));
1171   ECHECK(mp_rat_neg(in[0], in[1]));
1172 
1173   if (expect == MP_OK && mp_rat_compare(in[1], out[0]) != 0) {
1174     mp_rat_to_string(in[1], 10, g_output, OUTPUT_LIMIT);
1175     FAIL(OTHER_ERROR);
1176   }
1177   return true;
1178 }
1179 
test_qrecip(testspec_t * t,FILE * ofp)1180 bool test_qrecip(testspec_t* t, FILE* ofp) {
1181   mp_rat in[2], out[1];
1182   mp_result expect;
1183 
1184   ACHECK(parse_rat_values(t, in, out, &expect));
1185   ECHECK(mp_rat_recip(in[0], in[1]));
1186 
1187   if (expect == MP_OK && mp_rat_compare(in[1], out[0]) != 0) {
1188     mp_rat_to_string(in[1], 10, g_output, OUTPUT_LIMIT);
1189     FAIL(OTHER_ERROR);
1190   }
1191   return true;
1192 }
1193 
test_qabs(testspec_t * t,FILE * ofp)1194 bool test_qabs(testspec_t* t, FILE* ofp) {
1195   mp_rat in[2], out[1];
1196   mp_result expect;
1197 
1198   ACHECK(parse_rat_values(t, in, out, &expect));
1199   ECHECK(mp_rat_abs(in[0], in[1]));
1200 
1201   if (expect == MP_OK && mp_rat_compare(in[1], out[0]) != 0) {
1202     mp_rat_to_string(in[1], 10, g_output, OUTPUT_LIMIT);
1203     FAIL(OTHER_ERROR);
1204   }
1205   return true;
1206 }
1207 
test_qadd(testspec_t * t,FILE * ofp)1208 bool test_qadd(testspec_t* t, FILE* ofp) {
1209   mp_rat in[3], out[1];
1210   mp_result expect;
1211 
1212   ACHECK(parse_rat_values(t, in, out, &expect));
1213   ECHECK(mp_rat_add(in[0], in[1], in[2]));
1214 
1215   if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
1216     mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
1217     FAIL(OTHER_ERROR);
1218   }
1219   return true;
1220 }
1221 
test_qsub(testspec_t * t,FILE * ofp)1222 bool test_qsub(testspec_t* t, FILE* ofp) {
1223   mp_rat in[3], out[1];
1224   mp_result expect;
1225 
1226   ACHECK(parse_rat_values(t, in, out, &expect));
1227   ECHECK(mp_rat_sub(in[0], in[1], in[2]));
1228 
1229   if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
1230     mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
1231     FAIL(OTHER_ERROR);
1232   }
1233   return true;
1234 }
1235 
test_qmul(testspec_t * t,FILE * ofp)1236 bool test_qmul(testspec_t* t, FILE* ofp) {
1237   mp_rat in[3], out[1];
1238   mp_result expect;
1239 
1240   ACHECK(parse_rat_values(t, in, out, &expect));
1241   ECHECK(mp_rat_mul(in[0], in[1], in[2]));
1242 
1243   if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
1244     mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
1245     FAIL(OTHER_ERROR);
1246   }
1247   return true;
1248 }
1249 
test_qdiv(testspec_t * t,FILE * ofp)1250 bool test_qdiv(testspec_t* t, FILE* ofp) {
1251   mp_rat in[3], out[1];
1252   mp_result expect;
1253 
1254   ACHECK(parse_rat_values(t, in, out, &expect));
1255   ECHECK(mp_rat_div(in[0], in[1], in[2]));
1256 
1257   if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
1258     mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
1259     FAIL(OTHER_ERROR);
1260   }
1261   return true;
1262 }
1263 
test_qaddz(testspec_t * t,FILE * ofp)1264 bool test_qaddz(testspec_t* t, FILE* ofp) {
1265   mp_rat in[3], out[1];
1266   mp_result expect;
1267 
1268   ACHECK(parse_rat_values(t, in, out, &expect));
1269 
1270   if (!mp_rat_is_integer(in[1])) {
1271     fprintf(stderr,
1272             "Line %d: Second argument must be an integer (test_qaddz)\n",
1273             t->line);
1274     FAIL(MP_BADARG);
1275   }
1276 
1277   ECHECK(mp_rat_add_int(in[0], MP_NUMER_P(in[1]), in[2]));
1278 
1279   if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
1280     mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
1281     FAIL(OTHER_ERROR);
1282   }
1283   return true;
1284 }
1285 
test_qsubz(testspec_t * t,FILE * ofp)1286 bool test_qsubz(testspec_t* t, FILE* ofp) {
1287   mp_rat in[3], out[1];
1288   mp_result expect;
1289 
1290   ACHECK(parse_rat_values(t, in, out, &expect));
1291 
1292   if (!mp_rat_is_integer(in[1])) {
1293     fprintf(stderr,
1294             "Line %d: Second argument must be an integer (test_qsubz)\n",
1295             t->line);
1296     FAIL(MP_BADARG);
1297   }
1298 
1299   ECHECK(mp_rat_sub_int(in[0], MP_NUMER_P(in[1]), in[2]));
1300 
1301   if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
1302     mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
1303     FAIL(OTHER_ERROR);
1304   }
1305   return true;
1306 }
1307 
test_qmulz(testspec_t * t,FILE * ofp)1308 bool test_qmulz(testspec_t* t, FILE* ofp) {
1309   mp_rat in[3], out[1];
1310   mp_result expect;
1311 
1312   ACHECK(parse_rat_values(t, in, out, &expect));
1313 
1314   if (!mp_rat_is_integer(in[1])) {
1315     fprintf(stderr,
1316             "Line %d: Second argument must be an integer (test_qmulz)\n",
1317             t->line);
1318     FAIL(MP_BADARG);
1319   }
1320 
1321   ECHECK(mp_rat_mul_int(in[0], MP_NUMER_P(in[1]), in[2]));
1322 
1323   if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
1324     mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
1325     FAIL(OTHER_ERROR);
1326   }
1327   return true;
1328 }
1329 
test_qdivz(testspec_t * t,FILE * ofp)1330 bool test_qdivz(testspec_t* t, FILE* ofp) {
1331   mp_rat in[3], out[1];
1332   mp_result expect;
1333 
1334   ACHECK(parse_rat_values(t, in, out, &expect));
1335 
1336   if (!mp_rat_is_integer(in[1])) {
1337     fprintf(stderr,
1338             "Line %d: Second argument must be an integer (test_qdivz)\n",
1339             t->line);
1340     FAIL(MP_BADARG);
1341   }
1342 
1343   ECHECK(mp_rat_div_int(in[0], MP_NUMER_P(in[1]), in[2]));
1344 
1345   if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
1346     mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
1347     FAIL(OTHER_ERROR);
1348   }
1349   return true;
1350 }
1351 
test_qexpt(testspec_t * t,FILE * ofp)1352 bool test_qexpt(testspec_t* t, FILE* ofp) {
1353   mp_rat in[3], out[1];
1354   mp_result expect;
1355   mp_small power;
1356 
1357   ACHECK(parse_rat_values(t, in, out, &expect));
1358 
1359   if (!mp_rat_is_integer(in[1])) {
1360     fprintf(stderr,
1361             "Line %d: Second argument must be an integer (test_qexpt)\n",
1362             t->line);
1363     FAIL(MP_BADARG);
1364   }
1365 
1366   CHECK(mp_int_to_int(MP_NUMER_P(in[1]), &power));
1367   ECHECK(mp_rat_expt(in[0], power, in[2]));
1368 
1369   if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
1370     mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
1371     FAIL(OTHER_ERROR);
1372   }
1373   return true;
1374 }
1375 
test_qtostr(testspec_t * t,FILE * ofp)1376 bool test_qtostr(testspec_t* t, FILE* ofp) {
1377   mp_rat in[2];
1378   long radix;
1379   mp_result len;
1380 
1381   ACHECK(parse_rat_values(t, in, NULL, NULL));
1382   trim_line(t->input[1]);
1383   ACHECK(read_long(&radix, t->input[1]));
1384 
1385   if (radix < MP_MIN_RADIX || radix > MP_MAX_RADIX) {
1386     fprintf(stderr, "Line %d: Radix %ld out of range\n", t->line, radix);
1387     FAIL(MP_RANGE);
1388   }
1389 
1390   trim_line(t->output[0]);
1391   len = mp_rat_string_len(in[0], radix);
1392 
1393   CHECK(mp_rat_to_string(in[0], radix, g_output, len));
1394 
1395   if (strcmp(t->output[0], g_output) != 0) FAIL(OTHER_ERROR);
1396 
1397   return true;
1398 }
1399 
test_qtodec(testspec_t * t,FILE * ofp)1400 bool test_qtodec(testspec_t* t, FILE* ofp) {
1401   mp_rat in[4];
1402   long radix, prec, m;
1403   mp_round_mode rmode;
1404   mp_result res, expect = MP_OK, len;
1405 
1406   ACHECK(parse_rat_values(t, in, NULL, NULL));
1407 
1408   if (t->output[0][0] == '$' && !parse_result_code(t->output[0], &expect)) {
1409     fprintf(stderr, "Line %d: Invalid result code [%s]\n", t->line,
1410             t->output[0]);
1411     FAIL(OTHER_ERROR);
1412   }
1413 
1414   trim_line(t->input[1]);
1415   trim_line(t->input[2]);
1416   trim_line(t->input[3]);
1417   ACHECK(read_long(&radix, t->input[1]));
1418   ACHECK(read_long(&prec, t->input[2]));
1419   ACHECK(read_long(&m, t->input[3]));
1420   rmode = (mp_round_mode)m;
1421 
1422   if (prec < 0) {
1423     fprintf(stderr, "Line %d: Precision %ld out of range\n", t->line, prec);
1424     FAIL(MP_RANGE);
1425   }
1426 
1427   trim_line(t->output[0]);
1428   len = mp_rat_decimal_len(in[0], radix, prec);
1429   ECHECK((res = mp_rat_to_decimal(in[0], radix, prec, rmode, g_output, len)));
1430 
1431   if (res == MP_OK && strcmp(t->output[0], g_output) != 0) FAIL(OTHER_ERROR);
1432 
1433   return true;
1434 }
1435 
test_qrdec(testspec_t * t,FILE * ofp)1436 bool test_qrdec(testspec_t* t, FILE* ofp) {
1437   mp_rat out[1] = {NULL}, reg = g_qreg + 1;
1438   long radix;
1439   mp_result expect;
1440 
1441   ACHECK(parse_rat_values(t, NULL, out, &expect));
1442   trim_line(t->input[1]);
1443   ACHECK(read_long(&radix, t->input[1]));
1444 
1445   ECHECK(mp_rat_read_decimal(reg, radix, t->input[0]));
1446   if (expect == MP_OK && mp_rat_compare(reg, out[0]) != 0) {
1447     mp_rat_to_string(reg, 10, g_output, OUTPUT_LIMIT);
1448     FAIL(OTHER_ERROR);
1449   }
1450   return true;
1451 }
1452 
test_is_prime(testspec_t * t,FILE * OFP)1453 bool test_is_prime(testspec_t* t, FILE* OFP) {
1454   mp_int in[1] = {NULL};
1455   mp_result expect;
1456 
1457   ACHECK(parse_int_values(t, in, NULL, &expect));
1458   ECHECK(mp_int_is_prime(in[0]));
1459   return true;
1460 }
1461 
1462 /* Here there be dragons */
1463