/* read_data,c -- Read data file and check function. Copyright (C) 2008, 2009, 2010, 2011, 2012 INRIA This file is part of GNU MPC. GNU MPC is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see http://www.gnu.org/licenses/ . */ #include #include #include "mpc-tests.h" char *pathname; unsigned long line_number; /* file name with complete path and currently read line; kept globally to simplify parameter passing */ unsigned long test_line_number; /* start line of data test (which may extend over several lines) */ int nextchar; /* character appearing next in the file, may be EOF */ #define MPC_INEX_CMP(r, i, c) \ (((r) == TERNARY_NOT_CHECKED || (r) == MPC_INEX_RE(c)) \ && ((i) == TERNARY_NOT_CHECKED || (i) == MPC_INEX_IM (c))) #define MPFR_INEX_STR(inex) \ (inex) == TERNARY_NOT_CHECKED ? "?" \ : (inex) == +1 ? "+1" \ : (inex) == -1 ? "-1" : "0" static const char *mpfr_rnd_mode [] = { "GMP_RNDN", "GMP_RNDZ", "GMP_RNDU", "GMP_RNDD" }; const char *rnd_mode[] = { "MPC_RNDNN", "MPC_RNDZN", "MPC_RNDUN", "MPC_RNDDN", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "MPC_RNDNZ", "MPC_RNDZZ", "MPC_RNDUZ", "MPC_RNDDZ", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "MPC_RNDNU", "MPC_RNDZU", "MPC_RNDUU", "MPC_RNDDU", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "MPC_RNDND", "MPC_RNDZD", "MPC_RNDUD", "MPC_RNDDD", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", "undefined", }; /* file functions */ FILE * open_data_file (const char *file_name) { FILE *fp; char *src_dir; char default_srcdir[] = "."; src_dir = getenv ("srcdir"); if (src_dir == NULL) src_dir = default_srcdir; pathname = (char *) malloc ((strlen (src_dir)) + strlen (file_name) + 2); if (pathname == NULL) { printf ("Cannot allocate memory\n"); exit (1); } sprintf (pathname, "%s/%s", src_dir, file_name); fp = fopen (pathname, "r"); if (fp == NULL) { fprintf (stderr, "Unable to open %s\n", pathname); exit (1); } return fp; } void close_data_file (FILE *fp) { free (pathname); fclose (fp); } /* read primitives */ static void skip_line (FILE *fp) /* skips characters until reaching '\n' or EOF; */ /* '\n' is skipped as well */ { while (nextchar != EOF && nextchar != '\n') nextchar = getc (fp); if (nextchar != EOF) { line_number ++; nextchar = getc (fp); } } static void skip_whitespace (FILE *fp) /* skips over whitespace if any until reaching EOF */ /* or non-whitespace */ { while (isspace (nextchar)) { if (nextchar == '\n') line_number ++; nextchar = getc (fp); } } void skip_whitespace_comments (FILE *fp) /* skips over all whitespace and comments, if any */ { skip_whitespace (fp); while (nextchar == '#') { skip_line (fp); if (nextchar != EOF) skip_whitespace (fp); } } size_t read_string (FILE *fp, char **buffer_ptr, size_t buffer_length, const char *name) { size_t pos; char *buffer; pos = 0; buffer = *buffer_ptr; if (nextchar == '"') nextchar = getc (fp); else goto error; while (nextchar != EOF && nextchar != '"') { if (nextchar == '\n') line_number ++; if (pos + 1 > buffer_length) { buffer = (char *) realloc (buffer, 2 * buffer_length); if (buffer == NULL) { printf ("Cannot allocate memory\n"); exit (1); } buffer_length *= 2; } buffer[pos++] = (char) nextchar; nextchar = getc (fp); } if (nextchar != '"') goto error; if (pos + 1 > buffer_length) { buffer = (char *) realloc (buffer, buffer_length + 1); if (buffer == NULL) { printf ("Cannot allocate memory\n"); exit (1); } buffer_length *= 2; } buffer[pos] = '\0'; nextchar = getc (fp); skip_whitespace_comments (fp); *buffer_ptr = buffer; return buffer_length; error: printf ("Error: Unable to read %s in file '%s' line '%lu'\n", name, pathname, line_number); exit (1); } /* All following read routines skip over whitespace and comments; */ /* so after calling them, nextchar is either EOF or the beginning */ /* of a non-comment token. */ void read_ternary (FILE *fp, int* ternary) { switch (nextchar) { case '!': *ternary = TERNARY_ERROR; break; case '?': *ternary = TERNARY_NOT_CHECKED; break; case '+': *ternary = +1; break; case '0': *ternary = 0; break; case '-': *ternary = -1; break; default: printf ("Error: Unexpected ternary value '%c' in file '%s' line %lu\n", nextchar, pathname, line_number); exit (1); } nextchar = getc (fp); skip_whitespace_comments (fp); } void read_mpfr_rounding_mode (FILE *fp, mpfr_rnd_t* rnd) { switch (nextchar) { case 'n': case 'N': *rnd = GMP_RNDN; break; case 'z': case 'Z': *rnd = GMP_RNDZ; break; case 'u': case 'U': *rnd = GMP_RNDU; break; case 'd': case 'D': *rnd = GMP_RNDD; break; default: printf ("Error: Unexpected rounding mode '%c' in file '%s' line %lu\n", nextchar, pathname, line_number); exit (1); } nextchar = getc (fp); if (nextchar != EOF && !isspace (nextchar)) { printf ("Error: Rounding mode not followed by white space in file " "'%s' line %lu\n", pathname, line_number); exit (1); } skip_whitespace_comments (fp); } void read_mpc_rounding_mode (FILE *fp, mpc_rnd_t* rnd) { mpfr_rnd_t re, im; read_mpfr_rounding_mode (fp, &re); read_mpfr_rounding_mode (fp, &im); *rnd = MPC_RND (re, im); } void read_int (FILE *fp, int *nread, const char *name) { int n = 0; if (nextchar == EOF) { printf ("Error: Unexpected EOF when reading int " "in file '%s' line %lu\n", pathname, line_number); exit (1); } ungetc (nextchar, fp); n = fscanf (fp, "%i", nread); if (ferror (fp) || n == 0 || n == EOF) { printf ("Error: Cannot read %s in file '%s' line %lu\n", name, pathname, line_number); exit (1); } nextchar = getc (fp); skip_whitespace_comments (fp); } static void read_uint (FILE *fp, unsigned long int *ui) { int n = 0; if (nextchar == EOF) { printf ("Error: Unexpected EOF when reading uint " "in file '%s' line %lu\n", pathname, line_number); exit (1); } ungetc (nextchar, fp); n = fscanf (fp, "%lu", ui); if (ferror (fp) || n == 0 || n == EOF) { printf ("Error: Cannot read uint in file '%s' line %lu\n", pathname, line_number); exit (1); } nextchar = getc (fp); skip_whitespace_comments (fp); } static void read_sint (FILE *fp, long int *si) { int n = 0; if (nextchar == EOF) { printf ("Error: Unexpected EOF when reading sint " "in file '%s' line %lu\n", pathname, line_number); exit (1); } ungetc (nextchar, fp); n = fscanf (fp, "%li", si); if (ferror (fp) || n == 0 || n == EOF) { printf ("Error: Cannot read sint in file '%s' line %lu\n", pathname, line_number); exit (1); } nextchar = getc (fp); skip_whitespace_comments (fp); } mpfr_prec_t read_mpfr_prec (FILE *fp) { unsigned long prec; int n; if (nextchar == EOF) { printf ("Error: Unexpected EOF when reading mpfr precision " "in file '%s' line %lu\n", pathname, line_number); exit (1); } ungetc (nextchar, fp); n = fscanf (fp, "%lu", &prec); if (ferror (fp)) /* then also n == EOF */ perror ("Error when reading mpfr precision"); if (n == 0 || n == EOF || prec < MPFR_PREC_MIN || prec > MPFR_PREC_MAX) { printf ("Error: Impossible mpfr precision in file '%s' line %lu\n", pathname, line_number); exit (1); } nextchar = getc (fp); skip_whitespace_comments (fp); return (mpfr_prec_t) prec; } static void read_mpfr_mantissa (FILE *fp, mpfr_ptr x) { if (nextchar == EOF) { printf ("Error: Unexpected EOF when reading mpfr mantissa " "in file '%s' line %lu\n", pathname, line_number); exit (1); } ungetc (nextchar, fp); if (mpfr_inp_str (x, fp, 0, GMP_RNDN) == 0) { printf ("Error: Impossible to read mpfr mantissa " "in file '%s' line %lu\n", pathname, line_number); exit (1); } nextchar = getc (fp); skip_whitespace_comments (fp); } void read_mpfr (FILE *fp, mpfr_ptr x, int *known_sign) { int sign; mpfr_set_prec (x, read_mpfr_prec (fp)); sign = nextchar; read_mpfr_mantissa (fp, x); /* the sign always matters for regular values ('+' is implicit), but when no sign appears before 0 or Inf in the data file, it means that only absolute value must be checked. */ if (known_sign != NULL) *known_sign = (!mpfr_zero_p (x) && !mpfr_inf_p (x)) || sign == '+' || sign == '-'; } void read_mpc (FILE *fp, mpc_ptr z, known_signs_t *ks) { read_mpfr (fp, mpc_realref (z), ks == NULL ? NULL : &ks->re); read_mpfr (fp, mpc_imagref (z), ks == NULL ? NULL : &ks->im); } static void check_compatible (int inex, mpfr_t expected, mpfr_rnd_t rnd, const char *s) { if ((rnd == GMP_RNDU && inex == -1) || (rnd == GMP_RNDD && inex == +1) || (rnd == GMP_RNDZ && !mpfr_signbit (expected) && inex == +1) || (rnd == GMP_RNDZ && mpfr_signbit (expected) && inex == -1)) { if (s != NULL) printf ("Incompatible ternary value '%c' (%s part) in file '%s' line %lu\n", (inex == 1) ? '+' : '-', s, pathname, test_line_number); else printf ("Incompatible ternary value '%c' in file '%s' line %lu\n", (inex == 1) ? '+' : '-', pathname, test_line_number); } } /* read lines of data */ static void read_cc (FILE *fp, int *inex_re, int *inex_im, mpc_ptr expected, known_signs_t *signs, mpc_ptr op, mpc_rnd_t *rnd) { test_line_number = line_number; read_ternary (fp, inex_re); read_ternary (fp, inex_im); read_mpc (fp, expected, signs); read_mpc (fp, op, NULL); read_mpc_rounding_mode (fp, rnd); check_compatible (*inex_re, mpc_realref(expected), MPC_RND_RE(*rnd), "real"); check_compatible (*inex_im, mpc_imagref(expected), MPC_RND_IM(*rnd), "imag"); } static void read_fc (FILE *fp, int *inex, mpfr_ptr expected, int *sign, mpc_ptr op, mpfr_rnd_t *rnd) { test_line_number = line_number; read_ternary (fp, inex); read_mpfr (fp, expected, sign); read_mpc (fp, op, NULL); read_mpfr_rounding_mode (fp, rnd); check_compatible (*inex, expected, *rnd, NULL); } static void read_ccc (FILE *fp, int *inex_re, int *inex_im, mpc_ptr expected, known_signs_t *signs, mpc_ptr op1, mpc_ptr op2, mpc_rnd_t *rnd) { test_line_number = line_number; read_ternary (fp, inex_re); read_ternary (fp, inex_im); read_mpc (fp, expected, signs); read_mpc (fp, op1, NULL); read_mpc (fp, op2, NULL); read_mpc_rounding_mode (fp, rnd); check_compatible (*inex_re, mpc_realref(expected), MPC_RND_RE(*rnd), "real"); check_compatible (*inex_im, mpc_imagref(expected), MPC_RND_IM(*rnd), "imag"); } /* read lines of data for function with three mpc_t inputs and one mpc_t output like mpc_fma */ static void read_cccc (FILE *fp, int *inex_re, int *inex_im, mpc_ptr expected, known_signs_t *signs, mpc_ptr op1, mpc_ptr op2, mpc_ptr op3, mpc_rnd_t *rnd) { test_line_number = line_number; read_ternary (fp, inex_re); read_ternary (fp, inex_im); read_mpc (fp, expected, signs); read_mpc (fp, op1, NULL); read_mpc (fp, op2, NULL); read_mpc (fp, op3, NULL); read_mpc_rounding_mode (fp, rnd); check_compatible (*inex_re, mpc_realref(expected), MPC_RND_RE(*rnd), "real"); check_compatible (*inex_im, mpc_imagref(expected), MPC_RND_IM(*rnd), "imag"); } static void read_cfc (FILE *fp, int *inex_re, int *inex_im, mpc_ptr expected, known_signs_t *signs, mpfr_ptr op1, mpc_ptr op2, mpc_rnd_t *rnd) { test_line_number = line_number; read_ternary (fp, inex_re); read_ternary (fp, inex_im); read_mpc (fp, expected, signs); read_mpfr (fp, op1, NULL); read_mpc (fp, op2, NULL); read_mpc_rounding_mode (fp, rnd); check_compatible (*inex_re, mpc_realref(expected), MPC_RND_RE(*rnd), "real"); check_compatible (*inex_im, mpc_imagref(expected), MPC_RND_IM(*rnd), "imag"); } static void read_ccf (FILE *fp, int *inex_re, int *inex_im, mpc_ptr expected, known_signs_t *signs, mpc_ptr op1, mpfr_ptr op2, mpc_rnd_t *rnd) { test_line_number = line_number; read_ternary (fp, inex_re); read_ternary (fp, inex_im); read_mpc (fp, expected, signs); read_mpc (fp, op1, NULL); read_mpfr (fp, op2, NULL); read_mpc_rounding_mode (fp, rnd); check_compatible (*inex_re, mpc_realref(expected), MPC_RND_RE(*rnd), "real"); check_compatible (*inex_im, mpc_imagref(expected), MPC_RND_IM(*rnd), "imag"); } static void read_ccu (FILE *fp, int *inex_re, int *inex_im, mpc_ptr expected, known_signs_t *signs, mpc_ptr op1, unsigned long int *op2, mpc_rnd_t *rnd) { test_line_number = line_number; read_ternary (fp, inex_re); read_ternary (fp, inex_im); read_mpc (fp, expected, signs); read_mpc (fp, op1, NULL); read_uint (fp, op2); read_mpc_rounding_mode (fp, rnd); check_compatible (*inex_re, mpc_realref(expected), MPC_RND_RE(*rnd), "real"); check_compatible (*inex_im, mpc_imagref(expected), MPC_RND_IM(*rnd), "imag"); } static void read_ccs (FILE *fp, int *inex_re, int *inex_im, mpc_ptr expected, known_signs_t *signs, mpc_ptr op1, long int *op2, mpc_rnd_t *rnd) { test_line_number = line_number; read_ternary (fp, inex_re); read_ternary (fp, inex_im); read_mpc (fp, expected, signs); read_mpc (fp, op1, NULL); read_sint (fp, op2); read_mpc_rounding_mode (fp, rnd); check_compatible (*inex_re, mpc_realref(expected), MPC_RND_RE(*rnd), "real"); check_compatible (*inex_im, mpc_imagref(expected), MPC_RND_IM(*rnd), "imag"); } /* set MPFR flags to random values */ static void set_mpfr_flags (int counter) { if (counter & 1) mpfr_set_underflow (); else mpfr_clear_underflow (); if (counter & 2) mpfr_set_overflow (); else mpfr_clear_overflow (); /* the divide-by-0 flag was added in MPFR 3.1.0 */ #ifdef mpfr_set_divby0 if (counter & 4) mpfr_set_divby0 (); else mpfr_clear_divby0 (); #endif if (counter & 8) mpfr_set_nanflag (); else mpfr_clear_nanflag (); if (counter & 16) mpfr_set_inexflag (); else mpfr_clear_inexflag (); if (counter & 32) mpfr_set_erangeflag (); else mpfr_clear_erangeflag (); } /* Check MPFR flags: we allow that some flags are set internally by MPC, for example if MPC does internal computations (using MPFR) which yield an overflow, even if the final MPC result fits in the exponent range. However we don't allow MPC to *clear* the MPFR flags */ static void check_mpfr_flags (int counter) { int old, neu; old = (counter & 1) != 0; neu = mpfr_underflow_p () != 0; if (old && (neu == 0)) { printf ("Error, underflow flag has been modified from %d to %d\n", old, neu); exit (1); } old = (counter & 2) != 0; neu = mpfr_overflow_p () != 0; if (old && (neu == 0)) { printf ("Error, overflow flag has been modified from %d to %d\n", old, neu); exit (1); } #ifdef mpfr_divby0_p old = (counter & 4) != 0; neu = mpfr_divby0_p () != 0; if (old && (neu == 0)) { printf ("Error, divby0 flag has been modified from %d to %d\n", old, neu); exit (1); } #endif old = (counter & 8) != 0; neu = mpfr_nanflag_p () != 0; if (old && (neu == 0)) { printf ("Error, nanflag flag has been modified from %d to %d\n", old, neu); exit (1); } old = (counter & 16) != 0; neu = mpfr_inexflag_p () != 0; if (old && (neu == 0)) { printf ("Error, inexflag flag has been modified from %d to %d\n", old, neu); exit (1); } old = (counter & 32) != 0; neu = mpfr_erangeflag_p () != 0; if (old && (neu == 0)) { printf ("Error, erangeflag flag has been modified from %d to %d\n", old, neu); exit (1); } } /* data_check (function, data_file_name) checks function results against precomputed data in a file.*/ void data_check (mpc_function function, const char *file_name) { FILE *fp; int inex_re; mpfr_t x1, x2; mpfr_rnd_t mpfr_rnd = GMP_RNDN; int sign_real; int inex_im; mpc_t z1, z2, z3, z4, z5; mpc_rnd_t rnd = MPC_RNDNN; unsigned long int ui; long int si; known_signs_t signs; int inex = 0; static int rand_counter = 0; fp = open_data_file (file_name); /* 1. init needed variables */ mpc_init2 (z1, 2); switch (function.type) { case FC: mpfr_init (x1); mpfr_init (x2); break; case CC: case CCU: case CCS: mpc_init2 (z2, 2); mpc_init2 (z3, 2); break; case C_CC: mpc_init2 (z2, 2); mpc_init2 (z3, 2); mpc_init2 (z4, 2); break; case CCCC: mpc_init2 (z2, 2); mpc_init2 (z3, 2); mpc_init2 (z4, 2); mpc_init2 (z5, 2); break; case CFC: case CCF: mpfr_init (x1); mpc_init2 (z2, 2); mpc_init2 (z3, 2); break; default: ; } /* 2. read data file */ line_number = 1; nextchar = getc (fp); skip_whitespace_comments (fp); while (nextchar != EOF) { set_mpfr_flags (rand_counter); /* for each kind of function prototype: */ /* 3.1 read a line of data: expected result, parameters, rounding mode */ /* 3.2 compute function at the same precision as the expected result */ /* 3.3 compare this result with the expected one */ switch (function.type) { case FC: /* example mpc_norm */ read_fc (fp, &inex_re, x1, &sign_real, z1, &mpfr_rnd); mpfr_set_prec (x2, mpfr_get_prec (x1)); inex = function.pointer.FC (x2, z1, mpfr_rnd); if ((inex_re != TERNARY_NOT_CHECKED && inex_re != inex) || !same_mpfr_value (x1, x2, sign_real)) { mpfr_t got, expected; mpc_t op; op[0] = z1[0]; got[0] = x2[0]; expected[0] = x1[0]; printf ("%s(op) failed (%s:%lu)\nwith rounding mode %s\n", function.name, file_name, test_line_number, mpfr_rnd_mode[mpfr_rnd]); if (inex_re != TERNARY_NOT_CHECKED && inex_re != inex) printf("ternary value: got %s, expected %s\n", MPFR_INEX_STR (inex), MPFR_INEX_STR (inex_re)); MPC_OUT (op); printf (" "); MPFR_OUT (got); MPFR_OUT (expected); exit (1); } break; case CC: /* example mpc_log */ read_cc (fp, &inex_re, &inex_im, z1, &signs, z2, &rnd); mpfr_set_prec (mpc_realref (z3), MPC_PREC_RE (z1)); mpfr_set_prec (mpc_imagref (z3), MPC_PREC_IM (z1)); inex = function.pointer.CC (z3, z2, rnd); if (!MPC_INEX_CMP (inex_re, inex_im, inex) || !same_mpc_value (z3, z1, signs)) { mpc_t op, got, expected; /* display sensible variable names */ op[0] = z2[0]; expected[0]= z1[0]; got[0] = z3[0]; printf ("%s(op) failed (line %lu)\nwith rounding mode %s\n", function.name, test_line_number, rnd_mode[rnd]); if (!MPC_INEX_CMP (inex_re, inex_im, inex)) printf("ternary value: got %s, expected (%s, %s)\n", MPC_INEX_STR (inex), MPFR_INEX_STR (inex_re), MPFR_INEX_STR (inex_im)); MPC_OUT (op); printf (" "); MPC_OUT (got); MPC_OUT (expected); exit (1); } break; case C_CC: /* example mpc_mul */ read_ccc (fp, &inex_re, &inex_im, z1, &signs, z2, z3, &rnd); mpfr_set_prec (mpc_realref(z4), MPC_PREC_RE (z1)); mpfr_set_prec (mpc_imagref(z4), MPC_PREC_IM (z1)); inex = function.pointer.C_CC (z4, z2, z3, rnd); if (!MPC_INEX_CMP (inex_re, inex_im, inex) || !same_mpc_value (z4, z1, signs)) { /* display sensible variable names */ mpc_t op1, op2, got, expected; op1[0] = z2[0]; op2[0] = z3[0]; expected[0]= z1[0]; got[0] = z4[0]; printf ("%s(op) failed (line %lu)\nwith rounding mode %s\n", function.name, test_line_number, rnd_mode[rnd]); if (!MPC_INEX_CMP (inex_re, inex_im, inex)) printf("ternary value: got %s, expected (%s, %s)\n", MPC_INEX_STR (inex), MPFR_INEX_STR (inex_re), MPFR_INEX_STR (inex_im)); MPC_OUT (op1); MPC_OUT (op2); printf (" "); MPC_OUT (got); MPC_OUT (expected); exit (1); } if (function.properties & FUNC_PROP_SYMETRIC) { inex = function.pointer.C_CC (z4, z3, z2, rnd); if (!MPC_INEX_CMP (inex_re, inex_im, inex) || !same_mpc_value (z4, z1, signs)) { /* display sensible variable names */ mpc_t op1, op2, got, expected; op1[0] = z3[0]; op2[0] = z2[0]; expected[0]= z1[0]; got[0] = z4[0]; printf ("%s(op) failed (line %lu/symetric test)\n" "with rounding mode %s\n", function.name, test_line_number, rnd_mode[rnd]); if (!MPC_INEX_CMP (inex_re, inex_im, inex)) printf("ternary value: got %s, expected (%s, %s)\n", MPC_INEX_STR (inex), MPFR_INEX_STR (inex_re), MPFR_INEX_STR (inex_im)); MPC_OUT (op1); MPC_OUT (op2); printf (" "); MPC_OUT (got); MPC_OUT (expected); exit (1); } } break; case CCCC: /* example mpc_fma */ read_cccc (fp, &inex_re, &inex_im, z1, &signs, z2, z3, z4, &rnd); /* z1 is the expected value, z2, z3, z4 are the inputs, and z5 is the computed value */ mpfr_set_prec (mpc_realref(z5), MPC_PREC_RE (z1)); mpfr_set_prec (mpc_imagref(z5), MPC_PREC_IM (z1)); inex = function.pointer.CCCC (z5, z2, z3, z4, rnd); if (!MPC_INEX_CMP (inex_re, inex_im, inex) || !same_mpc_value (z5, z1, signs)) { /* display sensible variable names */ mpc_t op1, op2, op3, got, expected; op1[0] = z2[0]; op2[0] = z3[0]; op3[0] = z4[0]; expected[0]= z1[0]; got[0] = z5[0]; printf ("%s(op) failed (line %lu)\nwith rounding mode %s\n", function.name, test_line_number, rnd_mode[rnd]); if (!MPC_INEX_CMP (inex_re, inex_im, inex)) printf("ternary value: got %s, expected (%s, %s)\n", MPC_INEX_STR (inex), MPFR_INEX_STR (inex_re), MPFR_INEX_STR (inex_im)); MPC_OUT (op1); MPC_OUT (op2); MPC_OUT (op3); printf (" "); MPC_OUT (got); MPC_OUT (expected); exit (1); } if (function.properties & FUNC_PROP_SYMETRIC) { inex = function.pointer.CCCC (z5, z3, z2, z4, rnd); if (!MPC_INEX_CMP (inex_re, inex_im, inex) || !same_mpc_value (z5, z1, signs)) { /* display sensible variable names */ mpc_t op1, op2, op3, got, expected; op1[0] = z3[0]; op2[0] = z2[0]; op3[0] = z4[0]; expected[0]= z1[0]; got[0] = z5[0]; printf ("%s(op) failed (line %lu/symetric test)\n" "with rounding mode %s\n", function.name, test_line_number, rnd_mode[rnd]); if (!MPC_INEX_CMP (inex_re, inex_im, inex)) printf("ternary value: got %s, expected (%s, %s)\n", MPC_INEX_STR (inex), MPFR_INEX_STR (inex_re), MPFR_INEX_STR (inex_im)); MPC_OUT (op1); MPC_OUT (op2); MPC_OUT (op3); printf (" "); MPC_OUT (got); MPC_OUT (expected); exit (1); } } break; case CFC: /* example mpc_fr_div */ read_cfc (fp, &inex_re, &inex_im, z1, &signs, x1, z2, &rnd); mpfr_set_prec (mpc_realref(z3), MPC_PREC_RE (z1)); mpfr_set_prec (mpc_imagref(z3), MPC_PREC_IM (z1)); inex = function.pointer.CFC (z3, x1, z2, rnd); if (!MPC_INEX_CMP (inex_re, inex_im, inex) || !same_mpc_value (z3, z1, signs)) { /* display sensible variable names */ mpc_t op2, got, expected; mpfr_t op1; op1[0] = x1[0]; op2[0] = z2[0]; expected[0]= z1[0]; got[0] = z3[0]; printf ("%s(op) failed (line %lu)\nwith rounding mode %s\n", function.name, test_line_number, rnd_mode[rnd]); if (!MPC_INEX_CMP (inex_re, inex_im, inex)) printf("ternary value: got %s, expected (%s, %s)\n", MPC_INEX_STR (inex), MPFR_INEX_STR (inex_re), MPFR_INEX_STR (inex_im)); MPFR_OUT (op1); MPC_OUT (op2); printf (" "); MPC_OUT (got); MPC_OUT (expected); exit (1); } break; case CCF: /* example mpc_mul_fr */ read_ccf (fp, &inex_re, &inex_im, z1, &signs, z2, x1, &rnd); mpfr_set_prec (mpc_realref(z3), MPC_PREC_RE (z1)); mpfr_set_prec (mpc_imagref(z3), MPC_PREC_IM (z1)); inex = function.pointer.CCF (z3, z2, x1, rnd); if (!MPC_INEX_CMP (inex_re, inex_im, inex) || !same_mpc_value (z3, z1, signs)) { /* display sensible variable names */ mpc_t op1, got, expected; mpfr_t op2; op1[0] = z2[0]; op2[0] = x1[0]; expected[0]= z1[0]; got[0] = z3[0]; printf ("%s(op) failed (line %lu)\nwith rounding mode %s\n", function.name, test_line_number, rnd_mode[rnd]); if (!MPC_INEX_CMP (inex_re, inex_im, inex)) printf("ternary value: got %s, expected (%s, %s)\n", MPC_INEX_STR (inex), MPFR_INEX_STR (inex_re), MPFR_INEX_STR (inex_im)); MPC_OUT (op1); MPFR_OUT (op2); printf (" "); MPC_OUT (got); MPC_OUT (expected); exit (1); } break; case CCU: /* example mpc_pow_ui */ read_ccu (fp, &inex_re, &inex_im, z1, &signs, z2, &ui, &rnd); mpfr_set_prec (mpc_realref(z3), MPC_PREC_RE (z1)); mpfr_set_prec (mpc_imagref(z3), MPC_PREC_IM (z1)); inex = function.pointer.CCU (z3, z2, ui, rnd); if (!MPC_INEX_CMP (inex_re, inex_im, inex) || !same_mpc_value (z3, z1, signs)) { /* display sensible variable names */ mpc_t op1, got, expected; op1[0] = z2[0]; expected[0]= z1[0]; got[0] = z3[0]; printf ("%s(op) failed (line %lu)\nwith rounding mode %s\n", function.name, test_line_number, rnd_mode[rnd]); if (!MPC_INEX_CMP (inex_re, inex_im, inex)) printf("ternary value: got %s, expected (%s, %s)\n", MPC_INEX_STR (inex), MPFR_INEX_STR (inex_re), MPFR_INEX_STR (inex_im)); MPC_OUT (op1); printf ("op2 %lu\n ", ui); MPC_OUT (got); MPC_OUT (expected); exit (1); } break; case CCS: /* example mpc_pow_si */ read_ccs (fp, &inex_re, &inex_im, z1, &signs, z2, &si, &rnd); mpfr_set_prec (mpc_realref(z3), MPC_PREC_RE (z1)); mpfr_set_prec (mpc_imagref(z3), MPC_PREC_IM (z1)); inex = function.pointer.CCS (z3, z2, si, rnd); if (!MPC_INEX_CMP (inex_re, inex_im, inex) || !same_mpc_value (z3, z1, signs)) { /* display sensible variable names */ mpc_t op1, got, expected; op1[0] = z2[0]; expected[0]= z1[0]; got[0] = z3[0]; printf ("%s(op) failed (line %lu)\nwith rounding mode %s\n", function.name, test_line_number, rnd_mode[rnd]); if (!MPC_INEX_CMP (inex_re, inex_im, inex)) printf("ternary value: got %s, expected (%s, %s)\n", MPC_INEX_STR (inex), MPFR_INEX_STR (inex_re), MPFR_INEX_STR (inex_im)); MPC_OUT (op1); printf ("op2 %li\n ", si); MPC_OUT (got); MPC_OUT (expected); exit (1); } break; default: printf ("Unhandled function prototype %i in 'data_check'\n", function.type); exit (1); } /* check MPFR flags were not modified */ check_mpfr_flags (rand_counter); rand_counter ++; } /* 3. Clear used variables */ mpc_clear (z1); switch (function.type) { case FC: mpfr_clear (x1); mpfr_clear (x2); break; case CC: case CCU: case CCS: mpc_clear (z2); mpc_clear (z3); break; case C_CC: mpc_clear (z2); mpc_clear (z3); mpc_clear (z4); break; case CCCC: mpc_clear (z2); mpc_clear (z3); mpc_clear (z4); mpc_clear (z5); break; case CFC: case CCF: mpfr_clear (x1); mpc_clear (z2); mpc_clear (z3); break; default: ; } close_data_file (fp); }