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 */
38mp_result imath_errno;
39char* 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
65static char g_output[OUTPUT_LIMIT];
66static mpz_t g_zreg[NUM_REGS];
67static mpq_t g_qreg[NUM_REGS];
68static unsigned char g_bin1[OUTPUT_LIMIT];
69static unsigned char g_bin2[OUTPUT_LIMIT];
70
71extern void trim_line(char* line); /* borrowed from imtest.c */
72
73/* Read in a string with radix tags */
74static mp_result read_int_value(mp_int z, char* str);
75static 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) */
78static 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. */
83static bool parse_int_values(testspec_t* t, mp_int* in, mp_int* out,
84 mp_result* rval);
85static 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 */
89static 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. */
94static int parse_binary(char* str, unsigned char* buf, int limit);
95
96/* Clean up registers (called from atexit()) */
97static void done_testing(void);
98
99/*
100 * Utility subroutines for writing tests (explained above)
101 */
102
103static 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
134static 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(r: q, radix, str: str + 1);
164 else
165 return mp_rat_read_string(r: q, radix, str);
166}
167
168static 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(nptr: str, endptr: &end, base: radix);
198 return (end != str && *end == '\0');
199}
200
201static 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(line: str);
213
214 if (*str == '=') {
215 int k = abs(x: atoi(nptr: str + 1)) - 1;
216
217 if (k < 0 || k >= i) {
218 fprintf(stderr, format: "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(z: reg, str) != MP_OK) {
228 fprintf(stderr, format: "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(line: str);
243
244 if (strcmp(s1: str, s2: "?") == 0)
245 mp_int_zero(z: reg);
246 else if (*str == '$') {
247 mp_result code;
248
249 if (!parse_result_code(str, code: &code)) {
250 fprintf(stderr, format: "Line %d: Invalid result code [%s]\n", t->line, str);
251 return false;
252 } else if (rval == NULL) {
253 fprintf(stderr, format: "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(z: reg);
261 } else if (out != NULL && read_int_value(z: reg, str) != MP_OK) {
262 fprintf(stderr, format: "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
272static 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(line: str);
284
285 if (*str == '=') {
286 int k = abs(x: atoi(nptr: str + 1)) - 1;
287
288 if (k < 0 || k >= i) {
289 fprintf(stderr, format: "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(q: reg, str) != MP_OK) {
299 fprintf(stderr, format: "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(line: str);
314
315 if (strcmp(s1: str, s2: "?") == 0)
316 mp_rat_zero(r: reg);
317 else if (*str == '$') {
318 mp_result code;
319
320 if (!parse_result_code(str, code: &code)) {
321 fprintf(stderr, format: "Line %d: Invalid result code [%s]\n", t->line, str);
322 return false;
323 } else if (rval == NULL) {
324 fprintf(stderr, format: "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(r: reg);
332 } else if (out != NULL && read_rat_value(q: reg, str) != MP_OK) {
333 fprintf(stderr, format: "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
343static 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(z: &v, str: str + 2)) return false;
349
350 *code = (mp_result)v;
351 } else if (strcmp(s1: str + 1, s2: "MP_OK") == 0 ||
352 strcmp(s1: str + 1, s2: "MP_FALSE") == 0) {
353 *code = MP_OK;
354 } else if (strcmp(s1: str + 1, s2: "MP_TRUE") == 0) {
355 *code = MP_TRUE;
356 } else if (strcmp(s1: str + 1, s2: "MP_MEMORY") == 0) {
357 *code = MP_MEMORY;
358 } else if (strcmp(s1: str + 1, s2: "MP_RANGE") == 0) {
359 *code = MP_RANGE;
360 } else if (strcmp(s1: str + 1, s2: "MP_UNDEF") == 0) {
361 *code = MP_UNDEF;
362 } else if (strcmp(s1: str + 1, s2: "MP_TRUNC") == 0) {
363 *code = MP_TRUNC;
364 } else if (strcmp(s1: str + 1, s2: "MP_ROUND_UP") == 0) {
365 *code = MP_ROUND_UP;
366 } else if (strcmp(s1: str + 1, s2: "MP_ROUND_DOWN") == 0) {
367 *code = MP_ROUND_DOWN;
368 } else if (strcmp(s1: str + 1, s2: "MP_ROUND_HALF_UP") == 0) {
369 *code = MP_ROUND_HALF_UP;
370 } else if (strcmp(s1: str + 1, s2: "MP_ROUND_HALF_DOWN") == 0) {
371 *code = MP_ROUND_HALF_DOWN;
372 } else {
373 return false;
374 }
375 }
376
377 return true;
378}
379
380static int parse_binary(char* str, unsigned char* buf, int limit) {
381 int pos = 0;
382 char* tok;
383
384 trim_line(line: str);
385
386 for (tok = strtok(s: str, delim: "."); tok != NULL && pos < limit;
387 tok = strtok(NULL, delim: ".")) {
388 long v;
389
390 if (!read_long(z: &v, str: tok) || v > UCHAR_MAX || v < 0) return -1;
391
392 buf[pos++] = (unsigned char)v;
393 }
394
395 return pos;
396}
397
398static void done_testing(void) {
399 int i;
400
401 for (i = 0; i < NUM_REGS; ++i) {
402 mp_int_clear(z: g_zreg + i);
403 mp_rat_clear(r: g_qreg + i);
404 }
405}
406
407/*
408 * Global functions visible to callers outside this file.
409 */
410
411void 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
427void reset_registers(void) {
428 for (int i = 0; i < NUM_REGS; ++i) {
429 mp_int_zero(z: g_zreg + i);
430 mp_rat_zero(r: g_qreg + i);
431 }
432}
433
434bool 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(s1: t->code, s2: "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(a: in[0], b: out[0]) != 0) {
451 mp_int_to_string(z: in[0], radix: 10, str: g_output, OUTPUT_LIMIT);
452 FAIL(OTHER_ERROR);
453 }
454
455 return true;
456}
457
458bool 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(s1: t->code, s2: "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(a: in[0], b: out[0]) != 0) {
475 mp_int_to_string(z: in[0], radix: 10, str: g_output, OUTPUT_LIMIT);
476 FAIL(OTHER_ERROR);
477 }
478
479 return true;
480}
481
482bool 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(a: in[1], b: out[0]) != 0) {
490 mp_int_to_string(z: in[1], radix: 10, str: g_output, OUTPUT_LIMIT);
491 FAIL(OTHER_ERROR);
492 }
493
494 return true;
495}
496
497bool 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(a: in[1], b: out[0]) != 0) {
505 mp_int_to_string(z: in[1], radix: 10, str: g_output, OUTPUT_LIMIT);
506 FAIL(OTHER_ERROR);
507 }
508
509 return true;
510}
511
512bool 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(s1: t->code, s2: "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(a: in[2], b: out[0]) != 0) {
527 mp_int_to_string(z: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
528 FAIL(OTHER_ERROR);
529 }
530
531 return true;
532}
533
534bool 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(s1: t->code, s2: "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(a: in[2], b: out[0]) != 0) {
549 mp_int_to_string(z: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
550 FAIL(OTHER_ERROR);
551 }
552 return true;
553}
554
555bool 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(a: in[2], b: out[0]) != 0) {
563 mp_int_to_string(z: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
564 FAIL(OTHER_ERROR);
565 }
566 return true;
567}
568
569bool 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(a: in[2], b: out[0]) != 0) {
579 mp_int_to_string(z: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
580 FAIL(OTHER_ERROR);
581 }
582 return true;
583}
584
585bool 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(a: in[2], b: out[0]) != 0) {
595 mp_int_to_string(z: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
596 FAIL(OTHER_ERROR);
597 }
598 return true;
599}
600
601bool 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(a: in[1], b: out[0]) != 0) {
609 mp_int_to_string(z: in[1], radix: 10, str: g_output, OUTPUT_LIMIT);
610 FAIL(OTHER_ERROR);
611 }
612 return true;
613}
614
615bool 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(a: in[2], b: out[0]) != 0) ||
623 (mp_int_compare(a: in[3], b: out[1]) != 0))) {
624 int len;
625 char* str;
626
627 mp_int_to_string(z: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
628 str = g_output + (len = strlen(s: g_output));
629 *str++ = ',';
630 mp_int_to_string(z: in[3], radix: 10, str, OUTPUT_LIMIT - (len + 1));
631 FAIL(OTHER_ERROR);
632 }
633 return true;
634}
635
636bool 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(a: in[2], b: out[0]) != 0) ||
646 (mp_int_compare(a: in[3], b: out[1]) != 0))) {
647 int len;
648 char* str;
649
650 mp_int_to_string(z: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
651 str = g_output + (len = strlen(s: g_output));
652 *str++ = ',';
653 mp_int_to_string(z: in[3], radix: 10, str, OUTPUT_LIMIT - (len + 1));
654 FAIL(OTHER_ERROR);
655 }
656 return true;
657}
658
659bool 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(a: in[2], b: out[0]) != 0) || (rem != orem))) {
671 char* str;
672
673 mp_int_to_string(z: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
674 str = g_output + strlen(s: g_output);
675 *str++ = ',';
676 sprintf(s: str, format: "%ld", rem);
677 FAIL(OTHER_ERROR);
678 }
679 return true;
680}
681
682bool 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(a: in[2], b: out[0]) != 0) {
692 mp_int_to_string(z: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
693 FAIL(OTHER_ERROR);
694 }
695 return true;
696}
697
698bool 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(a: in[2], b: out[0]) != 0) {
709 mp_int_to_string(z: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
710 FAIL(OTHER_ERROR);
711 }
712 return true;
713}
714
715bool 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(a: in[2], b: out[0]) != 0) {
723 mp_int_to_string(z: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
724 FAIL(OTHER_ERROR);
725 }
726 return true;
727}
728
729bool 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(a: in[2], b: out[0]) != 0) {
737 mp_int_to_string(z: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
738 FAIL(OTHER_ERROR);
739 }
740 return true;
741}
742
743bool 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(a: in[2], b: out[0]) != 0) {
751 mp_int_to_string(z: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
752 FAIL(OTHER_ERROR);
753 }
754 return true;
755}
756
757bool 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(a: in[2], b: out[0]) != 0) ||
768 (mp_int_compare(a: in[3], b: out[1]) != 0) ||
769 (mp_int_compare(a: in[4], b: 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(a: in[3], b: in[0], c: t1);
777 mp_int_mul(a: in[4], b: in[1], c: t2);
778 mp_int_add(a: t1, b: t2, c: t2);
779 if (mp_int_compare(a: t2, b: in[2]) == 0) return true;
780
781 mp_int_to_string(z: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
782 str = g_output + (len = strlen(s: g_output));
783 *str++ = ',';
784 mp_int_to_string(z: in[3], radix: 10, str, OUTPUT_LIMIT - (len + 1));
785 str = str + (len2 = strlen(s: str));
786 *str++ = ',';
787 mp_int_to_string(z: in[4], radix: 10, str, OUTPUT_LIMIT - (len + len2 + 2));
788 FAIL(OTHER_ERROR);
789 }
790 return true;
791}
792
793bool 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(a: in[2], b: out[0]) != 0) {
801 mp_int_to_string(z: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
802 FAIL(OTHER_ERROR);
803 }
804 return true;
805}
806
807bool 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(a: in[1], b: out[0]) != 0) {
815 mp_int_to_string(z: in[1], radix: 10, str: g_output, OUTPUT_LIMIT);
816 FAIL(OTHER_ERROR);
817 }
818 return true;
819}
820
821bool 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(a: in[2], b: out[0]) != 0) {
831 mp_int_to_string(z: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
832 FAIL(OTHER_ERROR);
833 }
834 return true;
835}
836
837bool 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(a: in[2], b: out[0]) != 0) {
845 mp_int_to_string(z: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
846 FAIL(OTHER_ERROR);
847 }
848 return true;
849}
850
851bool 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(a: in[3], b: out[0]) != 0) {
859 mp_int_to_string(z: in[3], radix: 10, str: g_output, OUTPUT_LIMIT);
860 FAIL(OTHER_ERROR);
861 }
862 return true;
863}
864
865bool 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(a: in[3], b: out[0]) != 0) {
875 mp_int_to_string(z: in[3], radix: 10, str: g_output, OUTPUT_LIMIT);
876 FAIL(OTHER_ERROR);
877 }
878 return true;
879}
880
881bool 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(a: in[3], b: out[0]) != 0) {
891 mp_int_to_string(z: in[3], radix: 10, str: g_output, OUTPUT_LIMIT);
892 FAIL(OTHER_ERROR);
893 }
894 return true;
895}
896
897bool 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(a: in[0], b: in[1])) != expect) {
904 sprintf(s: g_output, format: "Incorrect comparison result (want %d, got %d)", expect,
905 res);
906 FAIL(OTHER_ERROR);
907 }
908 return true;
909}
910
911bool 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(a: in[0], b: in[1])) != expect) {
918 sprintf(s: g_output, format: "Incorrect comparison result (want %d, got %d)", expect,
919 res);
920 FAIL(OTHER_ERROR);
921 }
922 return true;
923}
924
925bool 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(z: in[0])) != expect) {
932 sprintf(s: g_output, format: "Incorrect comparison result (want %d, got %d)", expect,
933 res);
934 FAIL(OTHER_ERROR);
935 }
936 return true;
937}
938
939bool 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(nptr: t->input[1]);
947 if ((res = mp_int_compare_value(z: in[0], v)) != expect) {
948 sprintf(s: g_output, format: "Incorrect comparison result (want %d, got %d)", expect,
949 res);
950 FAIL(OTHER_ERROR);
951 }
952 return true;
953}
954
955bool 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(nptr: t->input[1], NULL, base: 0);
963 if ((res = mp_int_compare_uvalue(z: in[0], uv: v)) != expect) {
964 sprintf(s: g_output, format: "Incorrect comparison result (want %d, got %d)", expect,
965 res);
966 FAIL(OTHER_ERROR);
967 }
968 return true;
969}
970
971bool 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(line: t->output[0]);
982 len = mp_int_string_len(z: in[0], radix);
983
984 CHECK(mp_int_to_string(in[0], radix, g_output, len));
985
986 if (strcmp(s1: t->output[0], s2: g_output) != 0) FAIL(OTHER_ERROR);
987
988 return true;
989}
990
991bool 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(line: t->output[0]);
998 if ((out_len = parse_binary(str: t->output[0], buf: g_bin1, limit: sizeof(g_bin1))) < 0)
999 FAIL(MP_BADARG);
1000
1001 if ((test_len = mp_int_binary_len(z: in[0])) != out_len) {
1002 sprintf(s: g_output, format: "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(s1: g_bin1, s2: g_bin2, n: test_len) != 0) {
1010 int pos = 0, i;
1011
1012 for (i = 0; i < test_len - 1; ++i)
1013 pos += sprintf(s: g_output + pos, format: "%d.", g_bin2[i]);
1014
1015 sprintf(s: g_output + pos, format: "%d", g_bin2[i]);
1016 FAIL(OTHER_ERROR);
1017 }
1018 return true;
1019}
1020
1021bool 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(z: out[0], v) != 0) {
1030 sprintf(s: g_output, format: "Incorrect value (got %ld)", v);
1031 FAIL(OTHER_ERROR);
1032 }
1033 return true;
1034}
1035
1036bool 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(z: out[0], uv: v) != 0) {
1045 sprintf(s: g_output, format: "Incorrect value (got %lu)", v);
1046 FAIL(OTHER_ERROR);
1047 }
1048 return true;
1049}
1050
1051bool 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(line: t->input[0]);
1059 if ((in_len = parse_binary(str: t->input[0], buf: g_bin1, limit: 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(a: in, b: out[0]) != 0) {
1065 mp_int_to_string(z: in, radix: 10, str: g_output, OUTPUT_LIMIT);
1066 FAIL(OTHER_ERROR);
1067 }
1068 return true;
1069}
1070
1071bool 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(line: t->output[0]);
1078 if ((out_len = parse_binary(str: t->output[0], buf: g_bin1, limit: sizeof(g_bin1))) < 0)
1079 FAIL(MP_BADARG);
1080
1081 if ((test_len = mp_int_unsigned_len(z: in[0])) != out_len) {
1082 sprintf(s: g_output, format: "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(s1: g_bin1, s2: g_bin2, n: test_len) != 0) {
1090 int pos = 0, i;
1091
1092 for (i = 0; i < test_len - 1; ++i)
1093 pos += sprintf(s: g_output + pos, format: "%d.", g_bin2[i]);
1094
1095 sprintf(s: g_output + pos, format: "%d", g_bin2[i]);
1096 FAIL(OTHER_ERROR);
1097 }
1098 return true;
1099}
1100
1101bool 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(line: t->input[0]);
1109 if ((in_len = parse_binary(str: t->input[0], buf: g_bin1, limit: 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(a: in, b: out[0]) != 0) {
1115 mp_int_to_string(z: in, radix: 10, str: g_output, OUTPUT_LIMIT);
1116 FAIL(OTHER_ERROR);
1117 }
1118 return true;
1119}
1120
1121bool 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(nmemb: t->num_inputs, size: sizeof(mp_int));
1128 }
1129 if (t->num_outputs > 0) {
1130 out = calloc(nmemb: t->num_outputs, size: sizeof(mp_int));
1131 }
1132
1133 if (!parse_int_values(t, in, out, rval: &expect)) {
1134 if (in != NULL) free(ptr: in);
1135 if (out != NULL) free(ptr: out);
1136 FAIL(MP_BADARG);
1137 }
1138
1139 fprintf(stream: ofp, format: "Test '%s' defined at line %d\n", t->code, t->line);
1140 fprintf(stream: ofp, format: "Expected result: %d\n", expect);
1141 fprintf(stream: ofp, format: "Input values: %d\n", t->num_inputs);
1142 for (i = 0; i < t->num_inputs; ++i) {
1143 mp_int_to_string(z: in[i], radix: 10, str: g_output, OUTPUT_LIMIT);
1144
1145 fprintf(stream: ofp, format: " %2d.) %s", i + 1, g_output);
1146
1147 for (j = i - 1; j >= 0; --j)
1148 if (in[j] == in[i]) {
1149 fprintf(stream: ofp, format: " (=> %d)", j + 1);
1150 break;
1151 }
1152
1153 fputc(c: '\n', stream: ofp);
1154 }
1155 fprintf(stream: ofp, format: "Output values: %d\n", t->num_outputs);
1156 for (i = 0; i < t->num_outputs; ++i) {
1157 mp_int_to_string(z: out[i], radix: 10, str: g_output, OUTPUT_LIMIT);
1158
1159 fprintf(stream: ofp, format: " %2d.) %s\n", i + 1, g_output);
1160 }
1161 if (in != NULL) free(ptr: in);
1162 if (out != NULL) free(ptr: out);
1163 return true;
1164}
1165
1166bool 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(a: in[1], b: out[0]) != 0) {
1174 mp_rat_to_string(r: in[1], radix: 10, str: g_output, OUTPUT_LIMIT);
1175 FAIL(OTHER_ERROR);
1176 }
1177 return true;
1178}
1179
1180bool 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(a: in[1], b: out[0]) != 0) {
1188 mp_rat_to_string(r: in[1], radix: 10, str: g_output, OUTPUT_LIMIT);
1189 FAIL(OTHER_ERROR);
1190 }
1191 return true;
1192}
1193
1194bool 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(a: in[1], b: out[0]) != 0) {
1202 mp_rat_to_string(r: in[1], radix: 10, str: g_output, OUTPUT_LIMIT);
1203 FAIL(OTHER_ERROR);
1204 }
1205 return true;
1206}
1207
1208bool 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(a: in[2], b: out[0]) != 0) {
1216 mp_rat_to_string(r: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
1217 FAIL(OTHER_ERROR);
1218 }
1219 return true;
1220}
1221
1222bool 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(a: in[2], b: out[0]) != 0) {
1230 mp_rat_to_string(r: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
1231 FAIL(OTHER_ERROR);
1232 }
1233 return true;
1234}
1235
1236bool 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(a: in[2], b: out[0]) != 0) {
1244 mp_rat_to_string(r: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
1245 FAIL(OTHER_ERROR);
1246 }
1247 return true;
1248}
1249
1250bool 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(a: in[2], b: out[0]) != 0) {
1258 mp_rat_to_string(r: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
1259 FAIL(OTHER_ERROR);
1260 }
1261 return true;
1262}
1263
1264bool 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(r: in[1])) {
1271 fprintf(stderr,
1272 format: "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(a: in[2], b: out[0]) != 0) {
1280 mp_rat_to_string(r: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
1281 FAIL(OTHER_ERROR);
1282 }
1283 return true;
1284}
1285
1286bool 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(r: in[1])) {
1293 fprintf(stderr,
1294 format: "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(a: in[2], b: out[0]) != 0) {
1302 mp_rat_to_string(r: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
1303 FAIL(OTHER_ERROR);
1304 }
1305 return true;
1306}
1307
1308bool 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(r: in[1])) {
1315 fprintf(stderr,
1316 format: "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(a: in[2], b: out[0]) != 0) {
1324 mp_rat_to_string(r: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
1325 FAIL(OTHER_ERROR);
1326 }
1327 return true;
1328}
1329
1330bool 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(r: in[1])) {
1337 fprintf(stderr,
1338 format: "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(a: in[2], b: out[0]) != 0) {
1346 mp_rat_to_string(r: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
1347 FAIL(OTHER_ERROR);
1348 }
1349 return true;
1350}
1351
1352bool 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(r: in[1])) {
1360 fprintf(stderr,
1361 format: "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(a: in[2], b: out[0]) != 0) {
1370 mp_rat_to_string(r: in[2], radix: 10, str: g_output, OUTPUT_LIMIT);
1371 FAIL(OTHER_ERROR);
1372 }
1373 return true;
1374}
1375
1376bool 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(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, format: "Line %d: Radix %ld out of range\n", t->line, radix);
1387 FAIL(MP_RANGE);
1388 }
1389
1390 trim_line(line: t->output[0]);
1391 len = mp_rat_string_len(r: in[0], radix);
1392
1393 CHECK(mp_rat_to_string(in[0], radix, g_output, len));
1394
1395 if (strcmp(s1: t->output[0], s2: g_output) != 0) FAIL(OTHER_ERROR);
1396
1397 return true;
1398}
1399
1400bool 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(str: t->output[0], code: &expect)) {
1409 fprintf(stderr, format: "Line %d: Invalid result code [%s]\n", t->line,
1410 t->output[0]);
1411 FAIL(OTHER_ERROR);
1412 }
1413
1414 trim_line(line: t->input[1]);
1415 trim_line(line: t->input[2]);
1416 trim_line(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, format: "Line %d: Precision %ld out of range\n", t->line, prec);
1424 FAIL(MP_RANGE);
1425 }
1426
1427 trim_line(line: t->output[0]);
1428 len = mp_rat_decimal_len(r: 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(s1: t->output[0], s2: g_output) != 0) FAIL(OTHER_ERROR);
1432
1433 return true;
1434}
1435
1436bool 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(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(a: reg, b: out[0]) != 0) {
1447 mp_rat_to_string(r: reg, radix: 10, str: g_output, OUTPUT_LIMIT);
1448 FAIL(OTHER_ERROR);
1449 }
1450 return true;
1451}
1452
1453bool 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

source code of polly/lib/External/isl/imath/imdrover.c