summaryrefslogtreecommitdiffstats
path: root/polly/lib/External/isl/imath/imdrover.c
diff options
context:
space:
mode:
Diffstat (limited to 'polly/lib/External/isl/imath/imdrover.c')
-rw-r--r--polly/lib/External/isl/imath/imdrover.c1780
1 files changed, 1780 insertions, 0 deletions
diff --git a/polly/lib/External/isl/imath/imdrover.c b/polly/lib/External/isl/imath/imdrover.c
new file mode 100644
index 00000000000..be0de16cc8f
--- /dev/null
+++ b/polly/lib/External/isl/imath/imdrover.c
@@ -0,0 +1,1780 @@
+/*
+ Name: imdrover.c
+ Purpose: Keeper of the hordes of testing code.
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+
+ Copyright (C) 2002-2007 Michael J. Fromberger, All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <assert.h>
+
+#include "imdrover.h"
+#include "imath.h"
+#include "imrat.h"
+
+/* Globals visible from outside this file */
+mp_result imath_errno;
+char *imath_errmsg;
+
+/* Set imath_errno and return failure from a test. */
+#define FAIL(E) return (imath_errno = (E), 0)
+
+/* Check that an expression X yields the expected mp_result value V. */
+#define VCHECK(X, V) \
+do { \
+ mp_result res_; \
+ if ((res_ = (X)) != (V)) { \
+ FAIL(res_); \
+ } \
+} while(0)
+#define CHECK(X) VCHECK(X, MP_OK)
+#define ECHECK(X) VCHECK(X, expect)
+#define ACHECK(X) \
+do { \
+ if (!(X)) { \
+ FAIL(MP_BADARG); \
+ } \
+} while(0)
+
+#define OUTPUT_LIMIT 2048
+#define NUM_REGS 16
+#define OTHER_ERROR -1024
+
+static char g_output[OUTPUT_LIMIT];
+static mpz_t g_zreg[NUM_REGS];
+static mpq_t g_qreg[NUM_REGS];
+static unsigned char g_bin1[OUTPUT_LIMIT];
+static unsigned char g_bin2[OUTPUT_LIMIT];
+
+extern void trim_line(char *line); /* borrowed from imtest.c */
+
+/* Read in a string with radix tags */
+static mp_result read_int_value(mp_int z, char *str);
+static mp_result read_rat_value(mp_rat q, char *str);
+
+/* Read in a string with radix tags, as a long (not an mp_int) */
+static int read_long(long *z, char *str);
+
+/* Parse the input and output values and fill in pointers to the
+ registers containing them. Returns true if all is well, false
+ in case of error. Caller allocates in/out to correct sizes. */
+static int parse_int_values(testspec_t* t, mp_int *in, mp_int *out,
+ mp_result *rval);
+static int parse_rat_values(testspec_t* t, mp_rat *in, mp_rat *out,
+ mp_result *rval);
+
+/* Parse a result code name and return the corresponding result
+ code */
+static int parse_result_code(char *str, mp_result *code);
+
+/* Read in a dot-delimited binary sequence to the given buffer, and
+ return the number of bytes read. Returns < 0 in case of a syntax
+ error. Records no more than limit bytes. */
+static int parse_binary(char *str, unsigned char *buf, int limit);
+
+/* Clean up registers (called from atexit()) */
+static void done_testing(void);
+
+/*------------------------------------------------------------------------*/
+/* Utility subroutines for writing tests (explained above) */
+
+/* {{{ read_int_value(z, str) */
+
+static mp_result read_int_value(mp_int z, char *str)
+{
+ int radix = 10;
+
+ if(*str == '#') {
+ ++str;
+ switch(*str) {
+ case 'x': case 'X':
+ radix = 16;
+ break;
+ case 'd': case 'D':
+ radix = 10;
+ break;
+ case 'o': case 'O':
+ radix = 8;
+ break;
+ case 'b': case 'B':
+ radix = 2;
+ break;
+ default:
+ return MP_RANGE;
+ }
+ ++str;
+ }
+
+ return mp_int_read_string(z, radix, str);
+}
+
+/* }}} */
+
+/* {{{ read_rat_value(q, str) */
+
+static mp_result read_rat_value(mp_rat q, char *str)
+{
+ int radix = 10;
+
+ if(*str == '#') {
+ ++str;
+ switch(*str) {
+ case 'x': case 'X':
+ radix = 16;
+ break;
+ case 'd': case 'D':
+ radix = 10;
+ break;
+ case 'o': case 'O':
+ radix = 8;
+ break;
+ case 'b': case 'B':
+ radix = 2;
+ break;
+ default:
+ return MP_RANGE;
+ }
+ ++str;
+ }
+
+ if(*str == '@')
+ return mp_rat_read_decimal(q, radix, str + 1);
+ else
+ return mp_rat_read_string(q, radix, str);
+}
+
+/* }}} */
+
+/* {{{ read_long(z, str) */
+
+static int read_long(long *z, char *str)
+{
+ char *end;
+ int radix = 10;
+
+ if (*str == '#') {
+ ++str;
+ switch (*str) {
+ case 'x': case 'X':
+ radix = 16;
+ break;
+ case 'd': case 'D':
+ radix = 10;
+ break;
+ case 'o': case 'O':
+ radix = 8;
+ break;
+ case 'b': case 'B':
+ radix = 2;
+ break;
+ default:
+ return 0;
+ }
+ ++str;
+ }
+
+ *z = strtol(str, &end, radix);
+ return (end != str && *end == '\0');
+}
+
+/* }}} */
+
+/* {{{ parse_int_values(t, in, out) */
+
+static int parse_int_values(testspec_t* t, mp_int* in, mp_int* out,
+ mp_result* rval)
+{
+ int i, pos = 0;
+ char *str;
+
+ if (rval != NULL)
+ *rval = MP_OK; /* default */
+
+ if (in != NULL) {
+ for (i = 0; i < t->num_inputs; ++i) {
+ str = t->input[i];
+
+ trim_line(str);
+
+ if (*str == '=') {
+ int k = abs(atoi(str + 1)) - 1;
+
+ if (k < 0 || k >= i) {
+ fprintf(stderr, "Line %d: Invalid input back-reference [%s]\n",
+ t->line, str);
+ return 0;
+ }
+
+ in[i] = in[k];
+ }
+ else {
+ mp_int reg = g_zreg + pos++; /* grab next free register */
+
+ if (read_int_value(reg, str) != MP_OK) {
+ fprintf(stderr, "Line %d: Invalid input value [%s]\n",
+ t->line, str);
+ return 0;
+ }
+
+ in[i] = reg;
+ }
+ }
+ }
+
+ for (i = 0; i < t->num_outputs; ++i) {
+ mp_int reg = g_zreg + pos++;
+
+ str = t->output[i];
+
+ trim_line(str);
+
+ if (strcmp(str, "?") == 0)
+ mp_int_zero(reg);
+ else if (*str == '$') {
+ mp_result code;
+
+ if (!parse_result_code(str, &code)) {
+ fprintf(stderr, "Line %d: Invalid result code [%s]\n",
+ t->line, str);
+ return 0;
+ }
+ else if(rval == NULL) {
+ fprintf(stderr, "Line %d: Result code not permitted here [%s]\n",
+ t->line, str);
+ return 0;
+ }
+ else
+ *rval = code;
+
+ /* Provide a dummy value for the corresponding output */
+ mp_int_zero(reg);
+ }
+ else if (out != NULL && read_int_value(reg, str) != MP_OK) {
+ fprintf(stderr, "Line %d: Invalid output value [%s]\n",
+ t->line, str);
+ return 0;
+ }
+
+ if (out != NULL)
+ out[i] = reg;
+ }
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ parse_rat_values(t, in, out) */
+
+static int parse_rat_values(testspec_t* t, mp_rat *in, mp_rat *out,
+ mp_result *rval)
+{
+ int i, pos = 0;
+ char *str;
+
+ if (rval != NULL)
+ *rval = MP_OK; /* default */
+
+ if (in != NULL) {
+ for (i = 0; i < t->num_inputs; ++i) {
+ str = t->input[i];
+
+ trim_line(str);
+
+ if (*str == '=') {
+ int k = abs(atoi(str + 1)) - 1;
+
+ if (k < 0 || k >= i) {
+ fprintf(stderr, "Line %d: Invalid input back-reference [%s]\n",
+ t->line, str);
+ return 0;
+ }
+
+ in[i] = in[k];
+ }
+ else {
+ mp_rat reg = g_qreg + pos++; /* grab next free register */
+
+ if (read_rat_value(reg, str) != MP_OK) {
+ fprintf(stderr, "Line %d: Invalid input value [%s]\n",
+ t->line, str);
+ return 0;
+ }
+
+ in[i] = reg;
+ }
+ }
+ }
+
+ for (i = 0; i < t->num_outputs; ++i) {
+ mp_rat reg = g_qreg + pos++;
+
+ str = t->output[i];
+
+ trim_line(str);
+
+ if (strcmp(str, "?") == 0)
+ mp_rat_zero(reg);
+ else if (*str == '$') {
+ mp_result code;
+
+ if (!parse_result_code(str, &code)) {
+ fprintf(stderr, "Line %d: Invalid result code [%s]\n",
+ t->line, str);
+ return 0;
+ }
+ else if (rval == NULL) {
+ fprintf(stderr, "Line %d: Result code not permitted here [%s]\n",
+ t->line, str);
+ return 0;
+ }
+ else
+ *rval = code;
+
+ /* Provide a dummy value for the corresponding output */
+ mp_rat_zero(reg);
+ }
+ else if (out != NULL && read_rat_value(reg, str) != MP_OK) {
+ fprintf(stderr, "Line %d: Invalid output value [%s]\n",
+ t->line, str);
+ return 0;
+ }
+
+ if (out != NULL)
+ out[i] = reg;
+ }
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ parse_result_code(str, *code) */
+
+static int parse_result_code(char *str, mp_result *code)
+{
+ if (str[0] == '$') {
+ if (str[1] == '#') {
+ long v;
+
+ if (!read_long(&v, str + 2))
+ return 0;
+
+ *code = (mp_result) v;
+ }
+ else if (strcmp(str + 1, "MP_OK") == 0 ||
+ strcmp(str + 1, "MP_FALSE") == 0)
+ *code = MP_OK;
+ else if (strcmp(str + 1, "MP_TRUE") == 0)
+ *code = MP_TRUE;
+ else if (strcmp(str + 1, "MP_MEMORY") == 0)
+ *code = MP_MEMORY;
+ else if (strcmp(str + 1, "MP_RANGE") == 0)
+ *code = MP_RANGE;
+ else if (strcmp(str + 1, "MP_UNDEF") == 0)
+ *code = MP_UNDEF;
+ else if (strcmp(str + 1, "MP_TRUNC") == 0)
+ *code = MP_TRUNC;
+ else if (strcmp(str + 1, "MP_ROUND_UP") == 0)
+ *code = MP_ROUND_UP;
+ else if (strcmp(str + 1, "MP_ROUND_DOWN") == 0)
+ *code = MP_ROUND_DOWN;
+ else if (strcmp(str + 1, "MP_ROUND_HALF_UP") == 0)
+ *code = MP_ROUND_HALF_UP;
+ else if (strcmp(str + 1, "MP_ROUND_HALF_DOWN") == 0)
+ *code = MP_ROUND_HALF_DOWN;
+ else
+ return 0;
+ }
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ parse_binary(str, buf, limit) */
+
+static int parse_binary(char *str, unsigned char *buf, int limit)
+{
+ int pos = 0;
+ char *tok;
+
+ trim_line(str);
+
+ for (tok = strtok(str, ".");
+ tok != NULL && pos < limit;
+ tok = strtok(NULL, ".")) {
+ long v;
+
+ if (!read_long(&v, tok) || v > UCHAR_MAX || v < 0)
+ return -1;
+
+ buf[pos++] = (unsigned char)v;
+ }
+
+ return pos;
+}
+
+/* }}} */
+
+/* {{{ done_testing() */
+
+static void done_testing(void)
+{
+ int i;
+
+ for (i = 0; i < NUM_REGS; ++i) {
+ mp_int_clear(g_zreg + i);
+ mp_rat_clear(g_qreg + i);
+ }
+}
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* Global functions visible to callers outside this file */
+
+/* {{{ init_testing() */
+
+void init_testing(void)
+{
+ static int is_done = 0;
+ int i;
+
+ if (is_done)
+ return;
+
+ for (i = 0; i < NUM_REGS; ++i) {
+ assert(mp_int_init(g_zreg + i) == MP_OK);
+ assert(mp_rat_init(g_qreg + i) == MP_OK);
+ }
+
+ imath_errmsg = g_output;
+
+ assert(atexit(done_testing) == 0);
+ is_done = 1;
+}
+
+/* }}} */
+
+/* {{{ reset_registers() */
+
+void reset_registers(void)
+{
+ int i;
+
+ for (i = 0; i < NUM_REGS; ++i) {
+ mp_int_zero(g_zreg + i);
+ mp_rat_zero(g_qreg + i);
+ }
+}
+
+/* }}} */
+
+int test_init(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2], out[1];
+ mp_small v;
+ mp_usmall uv;
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+
+ if (strcmp(t->code, "initu") == 0) {
+ CHECK(mp_int_to_uint(in[1], &uv));
+ ECHECK(mp_int_init_uvalue(in[0], uv));
+ }
+ else { /* initv */
+ CHECK(mp_int_to_int(in[1], &v));
+ ECHECK(mp_int_init_value(in[0], v));
+ }
+
+
+ if (expect == MP_OK && mp_int_compare(in[0], out[0]) != 0) {
+ mp_int_to_string(in[0], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+
+ return 1;
+}
+
+int test_set(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2], out[1];
+ mp_small v;
+ mp_usmall uv;
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+
+ if (strcmp(t->code, "setu") == 0) {
+ CHECK(mp_int_to_uint(in[1], &uv));
+ ECHECK(mp_int_set_uvalue(in[0], uv));
+ }
+ else { /* setv */
+ CHECK(mp_int_to_int(in[1], &v));
+ ECHECK(mp_int_set_value(in[0], v));
+ }
+
+ if (expect == MP_OK && mp_int_compare(in[0], out[0]) != 0) {
+ mp_int_to_string(in[0], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+
+ return 1;
+}
+
+/* {{{ test_neg(t, ofp) */
+
+int test_neg(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_neg(in[0], in[1]));
+
+ if (expect == MP_OK && mp_int_compare(in[1], out[0]) != 0) {
+ mp_int_to_string(in[1], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_abs(t, ofp) */
+
+int test_abs(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_abs(in[0], in[1]));
+
+ if (expect == MP_OK && mp_int_compare(in[1], out[0]) != 0) {
+ mp_int_to_string(in[1], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_add(t, ofp) */
+
+int test_add(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_small v;
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+
+ if (strcmp(t->code, "addv") == 0) {
+ CHECK(mp_int_to_int(in[1], &v));
+ ECHECK(mp_int_add_value(in[0], v, in[2]));
+ }
+ else {
+ ECHECK(mp_int_add(in[0], in[1], in[2]));
+ }
+
+ if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_sub(t, ofp) */
+
+int test_sub(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_small v;
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+
+ if (strcmp(t->code, "subv") == 0) {
+ CHECK(mp_int_to_int(in[1], &v));
+ ECHECK(mp_int_sub_value(in[0], v, in[2]));
+ }
+ else {
+ ECHECK(mp_int_sub(in[0], in[1], in[2]));
+ }
+
+ if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_mul(t, ofp) */
+
+int test_mul(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_mul(in[0], in[1], in[2]));
+
+ if(expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_mulp2(t, ofp) */
+
+int test_mulp2(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_result expect;
+ mp_small p2;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ CHECK(mp_int_to_int(in[1], &p2));
+ ECHECK(mp_int_mul_pow2(in[0], p2, in[2]));
+
+ if(expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_mulv(t, ofp) */
+
+int test_mulv(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_result expect;
+ mp_small v;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ CHECK(mp_int_to_int(in[1], &v));
+ ECHECK(mp_int_mul_value(in[0], v, in[2]));
+
+ if(expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_sqr(t, ofp) */
+
+int test_sqr(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_sqr(in[0], in[1]));
+
+ if(expect == MP_OK && mp_int_compare(in[1], out[0]) != 0) {
+ mp_int_to_string(in[1], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_div(t, ofp) */
+
+int test_div(testspec_t* t, FILE* ofp)
+{
+ mp_int in[4], out[2];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_div(in[0], in[1], in[2], in[3]));
+
+ if (expect == MP_OK &&
+ ((mp_int_compare(in[2], out[0]) != 0) ||
+ (mp_int_compare(in[3], out[1]) != 0))) {
+ int len;
+ char *str;
+
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ str = g_output + (len = strlen(g_output));
+ *str++ = ',';
+ mp_int_to_string(in[3], 10, str, OUTPUT_LIMIT - (len + 1));
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_divp2(t, ofp) */
+
+int test_divp2(testspec_t* t, FILE* ofp)
+{
+ mp_int in[4], out[2];
+ mp_result expect;
+ mp_small p2;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ CHECK(mp_int_to_int(in[1], &p2));
+ ECHECK(mp_int_div_pow2(in[0], p2, in[2], in[3]));
+
+ if (expect == MP_OK &&
+ ((mp_int_compare(in[2], out[0]) != 0) ||
+ (mp_int_compare(in[3], out[1]) != 0))) {
+ int len;
+ char *str;
+
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ str = g_output + (len = strlen(g_output));
+ *str++ = ',';
+ mp_int_to_string(in[3], 10, str, OUTPUT_LIMIT - (len + 1));
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_divv(t, ofp) */
+
+int test_divv(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[2];
+ mp_result expect;
+ mp_small v, rem, orem;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ CHECK(mp_int_to_int(in[1], &v));
+ CHECK(mp_int_to_int(out[1], &orem));
+ ECHECK(mp_int_div_value(in[0], v, in[2], &rem));
+
+ if (expect == MP_OK &&
+ ((mp_int_compare(in[2], out[0]) != 0) || (rem != orem))) {
+ char *str;
+
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ str = g_output + strlen(g_output);
+ *str++ = ',';
+ sprintf(str, "%ld", rem);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_expt(t, ofp) */
+
+int test_expt(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_result expect;
+ mp_small pow;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ CHECK(mp_int_to_int(in[1], &pow));
+ ECHECK(mp_int_expt(in[0], pow, in[2]));
+
+ if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_exptv(t, ofp) */
+
+int test_exptv(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_result expect;
+ mp_small a, b;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ CHECK(mp_int_to_int(in[0], &a));
+ CHECK(mp_int_to_int(in[1], &b));
+ ECHECK(mp_int_expt_value(a, b, in[2]));
+
+ if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_exptf(t, ofp) */
+
+int test_exptf(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_expt_full(in[0], in[1], in[2]));
+
+ if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_mod(t, ofp) */
+
+int test_mod(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_mod(in[0], in[1], in[2]));
+
+ if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_gcd(t, ofp) */
+
+int test_gcd(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_gcd(in[0], in[1], in[2]));
+
+ if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_egcd(t, ofp) */
+
+int test_egcd(testspec_t* t, FILE* ofp)
+{
+ mp_int in[5], out[3], t1 = g_zreg + 8, t2 = g_zreg + 9;
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_egcd(in[0], in[1], in[2], in[3], in[4]));
+
+ /* If we got an error we expected, return success immediately */
+ if(expect != MP_OK)
+ return 1;
+
+ if ((mp_int_compare(in[2], out[0]) != 0) ||
+ (mp_int_compare(in[3], out[1]) != 0) ||
+ (mp_int_compare(in[4], out[2]) != 0)) {
+ int len, len2;
+ char *str;
+
+ /* Failure might occur because the tester computed x and y in a different
+ way than we did. Verify that the results are correct before reporting
+ an error. */
+ mp_int_mul(in[3], in[0], t1);
+ mp_int_mul(in[4], in[1], t2);
+ mp_int_add(t1, t2, t2);
+ if (mp_int_compare(t2, in[2]) == 0)
+ return 1;
+
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ str = g_output + (len = strlen(g_output));
+ *str++ = ',';
+ mp_int_to_string(in[3], 10, str, OUTPUT_LIMIT - (len + 1));
+ str = str + (len2 = strlen(str));
+ *str++ = ',';
+ mp_int_to_string(in[4], 10, str, OUTPUT_LIMIT - (len + len2 + 2));
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_lcm(t, ofp) */
+
+int test_lcm(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_lcm(in[0], in[1], in[2]));
+
+ if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_sqrt(t, ofp) */
+
+int test_sqrt(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_sqrt(in[0], in[1]));
+
+ if (expect == MP_OK && mp_int_compare(in[1], out[0]) != 0) {
+ mp_int_to_string(in[1], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_root(t, ofp) */
+
+int test_root(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_small v;
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ CHECK(mp_int_to_int(in[1], &v));
+ ECHECK(mp_int_root(in[0], v, in[2]));
+
+ if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_invmod(t, ofp) */
+
+int test_invmod(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_invmod(in[0], in[1], in[2]));
+
+ if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_exptmod(t, ofp) */
+
+int test_exptmod(testspec_t* t, FILE* ofp)
+{
+ mp_int in[4], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_exptmod(in[0], in[1], in[2], in[3]));
+
+ if (expect == MP_OK && mp_int_compare(in[3], out[0]) != 0) {
+ mp_int_to_string(in[3], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_exptmod_ev(t, ofp) */
+
+int test_exptmod_ev(testspec_t* t, FILE* ofp)
+{
+ mp_int in[4], out[1];
+ mp_result expect;
+ mp_small v;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ CHECK(mp_int_to_int(in[1], &v));
+ ECHECK(mp_int_exptmod_evalue(in[0], v, in[2], in[3]));
+
+ if (expect == MP_OK && mp_int_compare(in[3], out[0]) != 0) {
+ mp_int_to_string(in[3], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_exptmod_bv(t, ofp) */
+
+int test_exptmod_bv(testspec_t* t, FILE* ofp)
+{
+ mp_int in[4], out[1];
+ mp_result expect;
+ mp_small v;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ CHECK(mp_int_to_int(in[0], &v));
+ ECHECK(mp_int_exptmod_bvalue(v, in[1], in[2], in[3]));
+
+ if (expect == MP_OK && mp_int_compare(in[3], out[0]) != 0) {
+ mp_int_to_string(in[3], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_comp(t, ofp) */
+
+int test_comp(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2];
+ mp_result res, expect;
+
+ ACHECK(parse_int_values(t, in, NULL, &expect));
+
+ if ((res = mp_int_compare(in[0], in[1])) != expect) {
+ sprintf(g_output, "Incorrect comparison result (want %d, got %d)",
+ expect, res);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_ucomp(t, ofp) */
+
+int test_ucomp(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2];
+ mp_result res, expect;
+
+ ACHECK(parse_int_values(t, in, NULL, &expect));
+
+ if ((res = mp_int_compare_unsigned(in[0], in[1])) != expect) {
+ sprintf(g_output, "Incorrect comparison result (want %d, got %d)",
+ expect, res);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_zcomp(t, ofp) */
+
+int test_zcomp(testspec_t* t, FILE* ofp)
+{
+ mp_int in[1];
+ mp_result res, expect;
+
+ ACHECK(parse_int_values(t, in, NULL, &expect));
+
+ if ((res = mp_int_compare_zero(in[0])) != expect) {
+ sprintf(g_output, "Incorrect comparison result (want %d, got %d)",
+ expect, res);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_vcomp(t, ofp) */
+
+int test_vcomp(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2];
+ mp_result res, expect;
+ mp_small v;
+
+ ACHECK(parse_int_values(t, in, NULL, &expect));
+
+ v = atoi(t->input[1]);
+ if ((res = mp_int_compare_value(in[0], v)) != expect) {
+ sprintf(g_output, "Incorrect comparison result (want %d, got %d)",
+ expect, res);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_uvcomp(t, ofp) */
+
+int test_uvcomp(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2];
+ mp_result res, expect;
+ mp_usmall v;
+
+ ACHECK(parse_int_values(t, in, NULL, &expect));
+
+ v = strtoul(t->input[1], NULL, 0);
+ if ((res = mp_int_compare_uvalue(in[0], v)) != expect) {
+ sprintf(g_output, "Incorrect comparison result (want %d, got %d)",
+ expect, res);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_tostr(t, ofp) */
+
+int test_tostr(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2];
+ mp_small radix;
+ mp_result len;
+
+ ACHECK(parse_int_values(t, in, NULL, NULL));
+ ACHECK(mp_int_to_int(in[1], &radix) == MP_OK);
+
+ if (radix < MP_MIN_RADIX || radix > MP_MAX_RADIX)
+ FAIL(MP_RANGE);
+
+ trim_line(t->output[0]);
+ len = mp_int_string_len(in[0], radix);
+
+ CHECK(mp_int_to_string(in[0], radix, g_output, len));
+
+ if(strcmp(t->output[0], g_output) != 0)
+ FAIL(OTHER_ERROR);
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_tobin(t, ofp) */
+
+int test_tobin(testspec_t* t, FILE* ofp)
+{
+ mp_int in[1];
+ int test_len, out_len;
+
+ ACHECK(parse_int_values(t, in, NULL, NULL));
+
+ trim_line(t->output[0]);
+ if((out_len = parse_binary(t->output[0], g_bin1, sizeof(g_bin1))) < 0)
+ FAIL(MP_BADARG);
+
+ if((test_len = mp_int_binary_len(in[0])) != out_len) {
+ sprintf(g_output, "Output lengths do not match (want %d, got %d)",
+ test_len, out_len);
+ FAIL(OTHER_ERROR);
+ }
+
+ CHECK(mp_int_to_binary(in[0], g_bin2, sizeof(g_bin2)));
+
+ if (memcmp(g_bin1, g_bin2, test_len) != 0) {
+ int pos = 0, i;
+
+ for(i = 0; i < test_len - 1; ++i)
+ pos += sprintf(g_output + pos, "%d.", g_bin2[i]);
+
+ sprintf(g_output + pos, "%d", g_bin2[i]);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_to_int(t, ofp) */
+
+int test_to_int(testspec_t* t, FILE* ofp)
+{
+ mp_int in[1], out[1];
+ mp_small v;
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_to_int(in[0], &v));
+
+ if (expect == MP_OK && mp_int_compare_value(out[0], v) != 0) {
+ sprintf(g_output, "Incorrect value (got %ld)", v);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_to_uint(t, ofp) */
+
+int test_to_uint(testspec_t* t, FILE* ofp)
+{
+ mp_int in[1], out[1];
+ mp_usmall v;
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_to_uint(in[0], &v));
+
+ if (expect == MP_OK && mp_int_compare_uvalue(out[0], v) != 0) {
+ sprintf(g_output, "Incorrect value (got %lu)", v);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_read_binary(t, ofp) */
+
+int test_read_binary(testspec_t* t, FILE* ofp)
+{
+ mp_int out[1], in = g_zreg + 1;
+ int in_len;
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, NULL, out, &expect));
+
+ trim_line(t->input[0]);
+ if((in_len = parse_binary(t->input[0], g_bin1, sizeof(g_bin1))) < 0)
+ FAIL(MP_BADARG);
+
+ ECHECK(mp_int_read_binary(in, g_bin1, in_len));
+
+ if (expect == MP_OK && mp_int_compare(in, out[0]) != 0) {
+ mp_int_to_string(in, 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_to_uns(t, ofp) */
+
+int test_to_uns(testspec_t* t, FILE* ofp)
+{
+ mp_int in[1];
+ int test_len, out_len;
+
+ ACHECK(parse_int_values(t, in, NULL, NULL));
+
+ trim_line(t->output[0]);
+ if((out_len = parse_binary(t->output[0], g_bin1, sizeof(g_bin1))) < 0)
+ FAIL(MP_BADARG);
+
+ if((test_len = mp_int_unsigned_len(in[0])) != out_len) {
+ sprintf(g_output, "Output lengths do not match (want %d, got %d)",
+ test_len, out_len);
+ FAIL(OTHER_ERROR);
+ }
+
+ CHECK(mp_int_to_unsigned(in[0], g_bin2, sizeof(g_bin2)));
+
+ if (memcmp(g_bin1, g_bin2, test_len) != 0) {
+ int pos = 0, i;
+
+ for(i = 0; i < test_len - 1; ++i)
+ pos += sprintf(g_output + pos, "%d.", g_bin2[i]);
+
+ sprintf(g_output + pos, "%d", g_bin2[i]);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_read_uns(t, ofp) */
+
+int test_read_uns(testspec_t* t, FILE* ofp)
+{
+ mp_int out[1], in = g_zreg + 1;
+ int in_len;
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, NULL, out, &expect));
+
+ trim_line(t->input[0]);
+ if((in_len = parse_binary(t->input[0], g_bin1, sizeof(g_bin1))) < 0)
+ FAIL(MP_BADARG);
+
+ ECHECK(mp_int_read_unsigned(in, g_bin1, in_len));
+
+ if (expect == MP_OK && mp_int_compare(in, out[0]) != 0) {
+ mp_int_to_string(in, 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_meta(t, ofp) */
+
+int test_meta(testspec_t* t, FILE* ofp)
+{
+ mp_int *in = NULL, *out = NULL;
+ int i, j;
+ mp_result expect;
+
+ if (t->num_inputs > 0)
+ in = calloc(t->num_inputs, sizeof(mp_int));
+ if (t->num_outputs > 0)
+ out = calloc(t->num_outputs, sizeof(mp_int));
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+
+ fprintf(ofp, "Test '%s' defined at line %d\n",
+ t->code, t->line);
+ fprintf(ofp, "Expected result: %d\n", expect);
+ fprintf(ofp, "Input values: %d\n", t->num_inputs);
+ for (i = 0; i < t->num_inputs; ++i) {
+ mp_int_to_string(in[i], 10, g_output, OUTPUT_LIMIT);
+
+ fprintf(ofp, " %2d.) %s", i + 1, g_output);
+
+ for (j = i - 1; j >= 0; --j)
+ if (in[j] == in[i]) {
+ fprintf(ofp, " (=> %d)", j + 1);
+ break;
+ }
+
+ fputc('\n', ofp);
+ }
+ fprintf(ofp, "Output values: %d\n", t->num_outputs);
+ for (i = 0; i < t->num_outputs; ++i) {
+ mp_int_to_string(out[i], 10, g_output, OUTPUT_LIMIT);
+
+ fprintf(ofp, " %2d.) %s\n", i + 1, g_output);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qneg(t, ofp) */
+
+int test_qneg(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[2], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+ ECHECK(mp_rat_neg(in[0], in[1]));
+
+ if (expect == MP_OK && mp_rat_compare(in[1], out[0]) != 0) {
+ mp_rat_to_string(in[1], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qrecip(t, ofp) */
+
+int test_qrecip(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[2], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+ ECHECK(mp_rat_recip(in[0], in[1]));
+
+ if (expect == MP_OK && mp_rat_compare(in[1], out[0]) != 0) {
+ mp_rat_to_string(in[1], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qabs(t, ofp) */
+
+int test_qabs(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[2], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+ ECHECK(mp_rat_abs(in[0], in[1]));
+
+ if (expect == MP_OK && mp_rat_compare(in[1], out[0]) != 0) {
+ mp_rat_to_string(in[1], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qadd(t, ofp) */
+
+int test_qadd(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+ ECHECK(mp_rat_add(in[0], in[1], in[2]));
+
+ if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
+ mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qsub(t, ofp) */
+
+int test_qsub(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+ ECHECK(mp_rat_sub(in[0], in[1], in[2]));
+
+ if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
+ mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qmul(t, ofp) */
+
+int test_qmul(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+ ECHECK(mp_rat_mul(in[0], in[1], in[2]));
+
+ if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
+ mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qdiv(t, ofp) */
+
+int test_qdiv(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+ ECHECK(mp_rat_div(in[0], in[1], in[2]));
+
+ if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
+ mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qaddz(t, ofp) */
+
+int test_qaddz(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+
+ if (!mp_rat_is_integer(in[1])) {
+ fprintf(stderr, "Line %d: Second argument must be an integer (test_qaddz)\n",
+ t->line);
+ FAIL(MP_BADARG);
+ }
+
+ ECHECK(mp_rat_add_int(in[0], MP_NUMER_P(in[1]), in[2]));
+
+ if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
+ mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qsubz(t, ofp) */
+
+int test_qsubz(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+
+ if (!mp_rat_is_integer(in[1])) {
+ fprintf(stderr, "Line %d: Second argument must be an integer (test_qsubz)\n",
+ t->line);
+ FAIL(MP_BADARG);
+ }
+
+ ECHECK(mp_rat_sub_int(in[0], MP_NUMER_P(in[1]), in[2]));
+
+ if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
+ mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qmulz(t, ofp) */
+
+int test_qmulz(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+
+ if (!mp_rat_is_integer(in[1])) {
+ fprintf(stderr, "Line %d: Second argument must be an integer (test_qmulz)\n",
+ t->line);
+ FAIL(MP_BADARG);
+ }
+
+ ECHECK(mp_rat_mul_int(in[0], MP_NUMER_P(in[1]), in[2]));
+
+ if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
+ mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qdivz(t, ofp) */
+
+int test_qdivz(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+
+ if (!mp_rat_is_integer(in[1])) {
+ fprintf(stderr, "Line %d: Second argument must be an integer (test_qdivz)\n",
+ t->line);
+ FAIL(MP_BADARG);
+ }
+
+ ECHECK(mp_rat_div_int(in[0], MP_NUMER_P(in[1]), in[2]));
+
+ if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
+ mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qexpt(t, ofp) */
+
+int test_qexpt(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[3], out[1];
+ mp_result expect;
+ mp_small power;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+
+ if (!mp_rat_is_integer(in[1])) {
+ fprintf(stderr, "Line %d: Second argument must be an integer (test_qexpt)\n",
+ t->line);
+ FAIL(MP_BADARG);
+ }
+
+ CHECK(mp_int_to_int(MP_NUMER_P(in[1]), &power));
+ ECHECK(mp_rat_expt(in[0], power, in[2]));
+
+ if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
+ mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qtostr(t, ofp) */
+
+int test_qtostr(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[2];
+ long radix;
+ mp_result len;
+
+ ACHECK(parse_rat_values(t, in, NULL, NULL));
+ trim_line(t->input[1]);
+ ACHECK(read_long(&radix, t->input[1]));
+
+ if (radix < MP_MIN_RADIX || radix > MP_MAX_RADIX) {
+ fprintf(stderr, "Line %d: Radix %ld out of range\n",
+ t->line, radix);
+ FAIL(MP_RANGE);
+ }
+
+ trim_line(t->output[0]);
+ len = mp_rat_string_len(in[0], radix);
+
+ CHECK(mp_rat_to_string(in[0], radix, g_output, len));
+
+ if (strcmp(t->output[0], g_output) != 0)
+ FAIL(OTHER_ERROR);
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qtodec(t, ofp) */
+
+int test_qtodec(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[4];
+ long radix, prec, m;
+ mp_round_mode rmode;
+ mp_result res, expect = MP_OK, len;
+
+ ACHECK(parse_rat_values(t, in, NULL, NULL));
+
+ if (t->output[0][0] == '$' && !parse_result_code(t->output[0], &expect)) {
+ fprintf(stderr, "Line %d: Invalid result code [%s]\n",
+ t->line, t->output[0]);
+ FAIL(OTHER_ERROR);
+ }
+
+ trim_line(t->input[1]);
+ trim_line(t->input[2]);
+ trim_line(t->input[3]);
+ ACHECK(read_long(&radix, t->input[1]));
+ ACHECK(read_long(&prec, t->input[2]));
+ ACHECK(read_long(&m, t->input[3]));
+ rmode = (mp_round_mode) m;
+
+ if (prec < 0) {
+ fprintf(stderr, "Line %d: Precision %ld out of range\n",
+ t->line, prec);
+ FAIL(MP_RANGE);
+ }
+
+ trim_line(t->output[0]);
+ len = mp_rat_decimal_len(in[0], radix, prec);
+ ECHECK((res = mp_rat_to_decimal(in[0], radix, prec, rmode, g_output, len)));
+
+ if (res == MP_OK && strcmp(t->output[0], g_output) != 0)
+ FAIL(OTHER_ERROR);
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qrdec(t, ofp) */
+
+int test_qrdec(testspec_t* t, FILE* ofp)
+{
+ mp_rat out[1], reg = g_qreg + 1;
+ long radix;
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, NULL, out, &expect));
+ trim_line(t->input[1]);
+ ACHECK(read_long(&radix, t->input[1]));
+
+ ECHECK(mp_rat_read_decimal(reg, radix, t->input[0]));
+ if (expect == MP_OK &&
+ mp_rat_compare(reg, out[0]) != 0) {
+ mp_rat_to_string(reg, 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* Here there be dragons */
OpenPOWER on IntegriCloud