/* Read data file and check function. Copyright (C) INRIA, 2008, 2009, 2010, 2011 This file is part of the MPC Library. The MPC Library 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 2.1 of the License, or (at your option) any later version. The MPC Library 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 the MPC Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #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 = RNDC (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); } 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_RE (z), ks == NULL ? NULL : &ks->re); read_mpfr (fp, MPC_IM (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) == 0 && inex == +1) || (rnd == GMP_RNDZ && mpfr_signbit (expected) == 1 && 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_RE(expected), MPC_RND_RE(*rnd), "real"); check_compatible (*inex_im, MPC_IM(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_RE(expected), MPC_RND_RE(*rnd), "real"); check_compatible (*inex_im, MPC_IM(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_RE(expected), MPC_RND_RE(*rnd), "real"); check_compatible (*inex_im, MPC_IM(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_RE(expected), MPC_RND_RE(*rnd), "real"); check_compatible (*inex_im, MPC_IM(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_RE(expected), MPC_RND_RE(*rnd), "real"); check_compatible (*inex_im, MPC_IM(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_RE(expected), MPC_RND_RE(*rnd), "real"); check_compatible (*inex_im, MPC_IM(expected), MPC_RND_IM(*rnd), "imag"); } /* 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; known_signs_t signs; int inex = 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: 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) { /* 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_RE (z3), MPC_PREC_RE (z1)); mpfr_set_prec (MPC_IM (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_RE(z4), MPC_PREC_RE (z1)); mpfr_set_prec (MPC_IM(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_RE(z5), MPC_PREC_RE (z1)); mpfr_set_prec (MPC_IM(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_RE(z3), MPC_PREC_RE (z1)); mpfr_set_prec (MPC_IM(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_RE(z3), MPC_PREC_RE (z1)); mpfr_set_prec (MPC_IM(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_RE(z3), MPC_PREC_RE (z1)); mpfr_set_prec (MPC_IM(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; default: ; } } /* 3. Clear used variables */ mpc_clear (z1); switch (function.type) { case FC: mpfr_clear (x1); mpfr_clear (x2); break; case CC: case CCU: 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); }