diff options
Diffstat (limited to 'polly/lib/External/isl/imath/imdrover.c')
-rw-r--r-- | polly/lib/External/isl/imath/imdrover.c | 1780 |
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 */ |