1/* read_data,c -- Read data file and check function. 2 3Copyright (C) 2008, 2009, 2010, 2011, 2012 INRIA 4 5This file is part of GNU MPC. 6 7GNU MPC is free software; you can redistribute it and/or modify it under 8the terms of the GNU Lesser General Public License as published by the 9Free Software Foundation; either version 3 of the License, or (at your 10option) any later version. 11 12GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY 13WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 15more details. 16 17You should have received a copy of the GNU Lesser General Public License 18along with this program. If not, see http://www.gnu.org/licenses/ . 19*/ 20 21#include <stdlib.h> 22#include <string.h> 23#include "mpc-tests.h" 24 25char *pathname; 26unsigned long line_number; 27 /* file name with complete path and currently read line; 28 kept globally to simplify parameter passing */ 29unsigned long test_line_number; 30 /* start line of data test (which may extend over several lines) */ 31int nextchar; 32 /* character appearing next in the file, may be EOF */ 33 34#define MPC_INEX_CMP(r, i, c) \ 35 (((r) == TERNARY_NOT_CHECKED || (r) == MPC_INEX_RE(c)) \ 36 && ((i) == TERNARY_NOT_CHECKED || (i) == MPC_INEX_IM (c))) 37 38#define MPFR_INEX_STR(inex) \ 39 (inex) == TERNARY_NOT_CHECKED ? "?" \ 40 : (inex) == +1 ? "+1" \ 41 : (inex) == -1 ? "-1" : "0" 42 43static const char *mpfr_rnd_mode [] = 44 { "GMP_RNDN", "GMP_RNDZ", "GMP_RNDU", "GMP_RNDD" }; 45 46const char *rnd_mode[] = 47 { "MPC_RNDNN", "MPC_RNDZN", "MPC_RNDUN", "MPC_RNDDN", 48 "undefined", "undefined", "undefined", "undefined", "undefined", 49 "undefined", "undefined", "undefined", "undefined", "undefined", 50 "undefined", "undefined", 51 "MPC_RNDNZ", "MPC_RNDZZ", "MPC_RNDUZ", "MPC_RNDDZ", 52 "undefined", "undefined", "undefined", "undefined", "undefined", 53 "undefined", "undefined", "undefined", "undefined", "undefined", 54 "undefined", "undefined", 55 "MPC_RNDNU", "MPC_RNDZU", "MPC_RNDUU", "MPC_RNDDU", 56 "undefined", "undefined", "undefined", "undefined", "undefined", 57 "undefined", "undefined", "undefined", "undefined", "undefined", 58 "undefined", "undefined", 59 "MPC_RNDND", "MPC_RNDZD", "MPC_RNDUD", "MPC_RNDDD", 60 "undefined", "undefined", "undefined", "undefined", "undefined", 61 "undefined", "undefined", "undefined", "undefined", "undefined", 62 "undefined", "undefined", 63 }; 64 65/* file functions */ 66FILE * 67open_data_file (const char *file_name) 68{ 69 FILE *fp; 70 char *src_dir; 71 char default_srcdir[] = "."; 72 73 src_dir = getenv ("srcdir"); 74 if (src_dir == NULL) 75 src_dir = default_srcdir; 76 77 pathname = (char *) malloc ((strlen (src_dir)) + strlen (file_name) + 2); 78 if (pathname == NULL) 79 { 80 printf ("Cannot allocate memory\n"); 81 exit (1); 82 } 83 sprintf (pathname, "%s/%s", src_dir, file_name); 84 fp = fopen (pathname, "r"); 85 if (fp == NULL) 86 { 87 fprintf (stderr, "Unable to open %s\n", pathname); 88 exit (1); 89 } 90 91 return fp; 92} 93 94void 95close_data_file (FILE *fp) 96{ 97 free (pathname); 98 fclose (fp); 99} 100 101/* read primitives */ 102static void 103skip_line (FILE *fp) 104 /* skips characters until reaching '\n' or EOF; */ 105 /* '\n' is skipped as well */ 106{ 107 while (nextchar != EOF && nextchar != '\n') 108 nextchar = getc (fp); 109 if (nextchar != EOF) 110 { 111 line_number ++; 112 nextchar = getc (fp); 113 } 114} 115 116static void 117skip_whitespace (FILE *fp) 118 /* skips over whitespace if any until reaching EOF */ 119 /* or non-whitespace */ 120{ 121 while (isspace (nextchar)) 122 { 123 if (nextchar == '\n') 124 line_number ++; 125 nextchar = getc (fp); 126 } 127} 128 129void 130skip_whitespace_comments (FILE *fp) 131 /* skips over all whitespace and comments, if any */ 132{ 133 skip_whitespace (fp); 134 while (nextchar == '#') { 135 skip_line (fp); 136 if (nextchar != EOF) 137 skip_whitespace (fp); 138 } 139} 140 141 142size_t 143read_string (FILE *fp, char **buffer_ptr, size_t buffer_length, const char *name) 144{ 145 size_t pos; 146 char *buffer; 147 148 pos = 0; 149 buffer = *buffer_ptr; 150 151 if (nextchar == '"') 152 nextchar = getc (fp); 153 else 154 goto error; 155 156 while (nextchar != EOF && nextchar != '"') 157 { 158 if (nextchar == '\n') 159 line_number ++; 160 if (pos + 1 > buffer_length) 161 { 162 buffer = (char *) realloc (buffer, 2 * buffer_length); 163 if (buffer == NULL) 164 { 165 printf ("Cannot allocate memory\n"); 166 exit (1); 167 } 168 buffer_length *= 2; 169 } 170 buffer[pos++] = (char) nextchar; 171 nextchar = getc (fp); 172 } 173 174 if (nextchar != '"') 175 goto error; 176 177 if (pos + 1 > buffer_length) 178 { 179 buffer = (char *) realloc (buffer, buffer_length + 1); 180 if (buffer == NULL) 181 { 182 printf ("Cannot allocate memory\n"); 183 exit (1); 184 } 185 buffer_length *= 2; 186 } 187 buffer[pos] = '\0'; 188 189 nextchar = getc (fp); 190 skip_whitespace_comments (fp); 191 192 *buffer_ptr = buffer; 193 194 return buffer_length; 195 196 error: 197 printf ("Error: Unable to read %s in file '%s' line '%lu'\n", 198 name, pathname, line_number); 199 exit (1); 200} 201 202/* All following read routines skip over whitespace and comments; */ 203/* so after calling them, nextchar is either EOF or the beginning */ 204/* of a non-comment token. */ 205void 206read_ternary (FILE *fp, int* ternary) 207{ 208 switch (nextchar) 209 { 210 case '!': 211 *ternary = TERNARY_ERROR; 212 break; 213 case '?': 214 *ternary = TERNARY_NOT_CHECKED; 215 break; 216 case '+': 217 *ternary = +1; 218 break; 219 case '0': 220 *ternary = 0; 221 break; 222 case '-': 223 *ternary = -1; 224 break; 225 default: 226 printf ("Error: Unexpected ternary value '%c' in file '%s' line %lu\n", 227 nextchar, pathname, line_number); 228 exit (1); 229 } 230 231 nextchar = getc (fp); 232 skip_whitespace_comments (fp); 233} 234 235void 236read_mpfr_rounding_mode (FILE *fp, mpfr_rnd_t* rnd) 237{ 238 switch (nextchar) 239 { 240 case 'n': case 'N': 241 *rnd = GMP_RNDN; 242 break; 243 case 'z': case 'Z': 244 *rnd = GMP_RNDZ; 245 break; 246 case 'u': case 'U': 247 *rnd = GMP_RNDU; 248 break; 249 case 'd': case 'D': 250 *rnd = GMP_RNDD; 251 break; 252 default: 253 printf ("Error: Unexpected rounding mode '%c' in file '%s' line %lu\n", 254 nextchar, pathname, line_number); 255 exit (1); 256 } 257 258 nextchar = getc (fp); 259 if (nextchar != EOF && !isspace (nextchar)) { 260 printf ("Error: Rounding mode not followed by white space in file " 261 "'%s' line %lu\n", 262 pathname, line_number); 263 exit (1); 264 } 265 skip_whitespace_comments (fp); 266} 267 268void 269read_mpc_rounding_mode (FILE *fp, mpc_rnd_t* rnd) 270{ 271 mpfr_rnd_t re, im; 272 read_mpfr_rounding_mode (fp, &re); 273 read_mpfr_rounding_mode (fp, &im); 274 *rnd = MPC_RND (re, im); 275} 276 277void 278read_int (FILE *fp, int *nread, const char *name) 279{ 280 int n = 0; 281 282 if (nextchar == EOF) 283 { 284 printf ("Error: Unexpected EOF when reading int " 285 "in file '%s' line %lu\n", 286 pathname, line_number); 287 exit (1); 288 } 289 ungetc (nextchar, fp); 290 n = fscanf (fp, "%i", nread); 291 if (ferror (fp) || n == 0 || n == EOF) 292 { 293 printf ("Error: Cannot read %s in file '%s' line %lu\n", 294 name, pathname, line_number); 295 exit (1); 296 } 297 nextchar = getc (fp); 298 skip_whitespace_comments (fp); 299} 300 301static void 302read_uint (FILE *fp, unsigned long int *ui) 303{ 304 int n = 0; 305 306 if (nextchar == EOF) 307 { 308 printf ("Error: Unexpected EOF when reading uint " 309 "in file '%s' line %lu\n", 310 pathname, line_number); 311 exit (1); 312 } 313 ungetc (nextchar, fp); 314 n = fscanf (fp, "%lu", ui); 315 if (ferror (fp) || n == 0 || n == EOF) 316 { 317 printf ("Error: Cannot read uint in file '%s' line %lu\n", 318 pathname, line_number); 319 exit (1); 320 } 321 nextchar = getc (fp); 322 skip_whitespace_comments (fp); 323} 324 325static void 326read_sint (FILE *fp, long int *si) 327{ 328 int n = 0; 329 330 if (nextchar == EOF) 331 { 332 printf ("Error: Unexpected EOF when reading sint " 333 "in file '%s' line %lu\n", 334 pathname, line_number); 335 exit (1); 336 } 337 ungetc (nextchar, fp); 338 n = fscanf (fp, "%li", si); 339 if (ferror (fp) || n == 0 || n == EOF) 340 { 341 printf ("Error: Cannot read sint in file '%s' line %lu\n", 342 pathname, line_number); 343 exit (1); 344 } 345 nextchar = getc (fp); 346 skip_whitespace_comments (fp); 347} 348 349mpfr_prec_t 350read_mpfr_prec (FILE *fp) 351{ 352 unsigned long prec; 353 int n; 354 355 if (nextchar == EOF) { 356 printf ("Error: Unexpected EOF when reading mpfr precision " 357 "in file '%s' line %lu\n", 358 pathname, line_number); 359 exit (1); 360 } 361 ungetc (nextchar, fp); 362 n = fscanf (fp, "%lu", &prec); 363 if (ferror (fp)) /* then also n == EOF */ 364 perror ("Error when reading mpfr precision"); 365 if (n == 0 || n == EOF || prec < MPFR_PREC_MIN || prec > MPFR_PREC_MAX) { 366 printf ("Error: Impossible mpfr precision in file '%s' line %lu\n", 367 pathname, line_number); 368 exit (1); 369 } 370 nextchar = getc (fp); 371 skip_whitespace_comments (fp); 372 return (mpfr_prec_t) prec; 373} 374 375static void 376read_mpfr_mantissa (FILE *fp, mpfr_ptr x) 377{ 378 if (nextchar == EOF) { 379 printf ("Error: Unexpected EOF when reading mpfr mantissa " 380 "in file '%s' line %lu\n", 381 pathname, line_number); 382 exit (1); 383 } 384 ungetc (nextchar, fp); 385 if (mpfr_inp_str (x, fp, 0, GMP_RNDN) == 0) { 386 printf ("Error: Impossible to read mpfr mantissa " 387 "in file '%s' line %lu\n", 388 pathname, line_number); 389 exit (1); 390 } 391 nextchar = getc (fp); 392 skip_whitespace_comments (fp); 393} 394 395void 396read_mpfr (FILE *fp, mpfr_ptr x, int *known_sign) 397{ 398 int sign; 399 mpfr_set_prec (x, read_mpfr_prec (fp)); 400 sign = nextchar; 401 read_mpfr_mantissa (fp, x); 402 403 /* the sign always matters for regular values ('+' is implicit), 404 but when no sign appears before 0 or Inf in the data file, it means 405 that only absolute value must be checked. */ 406 if (known_sign != NULL) 407 *known_sign = 408 (!mpfr_zero_p (x) && !mpfr_inf_p (x)) 409 || sign == '+' || sign == '-'; 410} 411 412void 413read_mpc (FILE *fp, mpc_ptr z, known_signs_t *ks) 414{ 415 read_mpfr (fp, mpc_realref (z), ks == NULL ? NULL : &ks->re); 416 read_mpfr (fp, mpc_imagref (z), ks == NULL ? NULL : &ks->im); 417} 418 419static void 420check_compatible (int inex, mpfr_t expected, mpfr_rnd_t rnd, const char *s) 421{ 422 if ((rnd == GMP_RNDU && inex == -1) || 423 (rnd == GMP_RNDD && inex == +1) || 424 (rnd == GMP_RNDZ && !mpfr_signbit (expected) && inex == +1) || 425 (rnd == GMP_RNDZ && mpfr_signbit (expected) && inex == -1)) 426 { 427 if (s != NULL) 428 printf ("Incompatible ternary value '%c' (%s part) in file '%s' line %lu\n", 429 (inex == 1) ? '+' : '-', s, pathname, test_line_number); 430 else 431 printf ("Incompatible ternary value '%c' in file '%s' line %lu\n", 432 (inex == 1) ? '+' : '-', pathname, test_line_number); 433 } 434} 435 436/* read lines of data */ 437static void 438read_cc (FILE *fp, int *inex_re, int *inex_im, mpc_ptr expected, 439 known_signs_t *signs, mpc_ptr op, mpc_rnd_t *rnd) 440{ 441 test_line_number = line_number; 442 read_ternary (fp, inex_re); 443 read_ternary (fp, inex_im); 444 read_mpc (fp, expected, signs); 445 read_mpc (fp, op, NULL); 446 read_mpc_rounding_mode (fp, rnd); 447 check_compatible (*inex_re, mpc_realref(expected), MPC_RND_RE(*rnd), "real"); 448 check_compatible (*inex_im, mpc_imagref(expected), MPC_RND_IM(*rnd), "imag"); 449} 450 451static void 452read_fc (FILE *fp, int *inex, mpfr_ptr expected, int *sign, mpc_ptr op, 453 mpfr_rnd_t *rnd) 454{ 455 test_line_number = line_number; 456 read_ternary (fp, inex); 457 read_mpfr (fp, expected, sign); 458 read_mpc (fp, op, NULL); 459 read_mpfr_rounding_mode (fp, rnd); 460 check_compatible (*inex, expected, *rnd, NULL); 461} 462 463static void 464read_ccc (FILE *fp, int *inex_re, int *inex_im, mpc_ptr expected, 465 known_signs_t *signs, mpc_ptr op1, mpc_ptr op2, mpc_rnd_t *rnd) 466{ 467 test_line_number = line_number; 468 read_ternary (fp, inex_re); 469 read_ternary (fp, inex_im); 470 read_mpc (fp, expected, signs); 471 read_mpc (fp, op1, NULL); 472 read_mpc (fp, op2, NULL); 473 read_mpc_rounding_mode (fp, rnd); 474 check_compatible (*inex_re, mpc_realref(expected), MPC_RND_RE(*rnd), "real"); 475 check_compatible (*inex_im, mpc_imagref(expected), MPC_RND_IM(*rnd), "imag"); 476} 477 478/* read lines of data for function with three mpc_t inputs and one mpc_t 479 output like mpc_fma */ 480static void 481read_cccc (FILE *fp, int *inex_re, int *inex_im, mpc_ptr expected, 482 known_signs_t *signs, mpc_ptr op1, mpc_ptr op2, mpc_ptr op3, 483 mpc_rnd_t *rnd) 484{ 485 test_line_number = line_number; 486 read_ternary (fp, inex_re); 487 read_ternary (fp, inex_im); 488 read_mpc (fp, expected, signs); 489 read_mpc (fp, op1, NULL); 490 read_mpc (fp, op2, NULL); 491 read_mpc (fp, op3, NULL); 492 read_mpc_rounding_mode (fp, rnd); 493 check_compatible (*inex_re, mpc_realref(expected), MPC_RND_RE(*rnd), "real"); 494 check_compatible (*inex_im, mpc_imagref(expected), MPC_RND_IM(*rnd), "imag"); 495} 496 497static void 498read_cfc (FILE *fp, int *inex_re, int *inex_im, mpc_ptr expected, 499 known_signs_t *signs, mpfr_ptr op1, mpc_ptr op2, mpc_rnd_t *rnd) 500{ 501 test_line_number = line_number; 502 read_ternary (fp, inex_re); 503 read_ternary (fp, inex_im); 504 read_mpc (fp, expected, signs); 505 read_mpfr (fp, op1, NULL); 506 read_mpc (fp, op2, NULL); 507 read_mpc_rounding_mode (fp, rnd); 508 check_compatible (*inex_re, mpc_realref(expected), MPC_RND_RE(*rnd), "real"); 509 check_compatible (*inex_im, mpc_imagref(expected), MPC_RND_IM(*rnd), "imag"); 510} 511 512static void 513read_ccf (FILE *fp, int *inex_re, int *inex_im, mpc_ptr expected, 514 known_signs_t *signs, mpc_ptr op1, mpfr_ptr op2, mpc_rnd_t *rnd) 515{ 516 test_line_number = line_number; 517 read_ternary (fp, inex_re); 518 read_ternary (fp, inex_im); 519 read_mpc (fp, expected, signs); 520 read_mpc (fp, op1, NULL); 521 read_mpfr (fp, op2, NULL); 522 read_mpc_rounding_mode (fp, rnd); 523 check_compatible (*inex_re, mpc_realref(expected), MPC_RND_RE(*rnd), "real"); 524 check_compatible (*inex_im, mpc_imagref(expected), MPC_RND_IM(*rnd), "imag"); 525} 526 527static void 528read_ccu (FILE *fp, int *inex_re, int *inex_im, mpc_ptr expected, 529 known_signs_t *signs, mpc_ptr op1, unsigned long int *op2, mpc_rnd_t *rnd) 530{ 531 test_line_number = line_number; 532 read_ternary (fp, inex_re); 533 read_ternary (fp, inex_im); 534 read_mpc (fp, expected, signs); 535 read_mpc (fp, op1, NULL); 536 read_uint (fp, op2); 537 read_mpc_rounding_mode (fp, rnd); 538 check_compatible (*inex_re, mpc_realref(expected), MPC_RND_RE(*rnd), "real"); 539 check_compatible (*inex_im, mpc_imagref(expected), MPC_RND_IM(*rnd), "imag"); 540} 541 542static void 543read_ccs (FILE *fp, int *inex_re, int *inex_im, mpc_ptr expected, 544 known_signs_t *signs, mpc_ptr op1, long int *op2, mpc_rnd_t *rnd) 545{ 546 test_line_number = line_number; 547 read_ternary (fp, inex_re); 548 read_ternary (fp, inex_im); 549 read_mpc (fp, expected, signs); 550 read_mpc (fp, op1, NULL); 551 read_sint (fp, op2); 552 read_mpc_rounding_mode (fp, rnd); 553 check_compatible (*inex_re, mpc_realref(expected), MPC_RND_RE(*rnd), "real"); 554 check_compatible (*inex_im, mpc_imagref(expected), MPC_RND_IM(*rnd), "imag"); 555} 556 557/* set MPFR flags to random values */ 558static void 559set_mpfr_flags (int counter) 560{ 561 if (counter & 1) 562 mpfr_set_underflow (); 563 else 564 mpfr_clear_underflow (); 565 if (counter & 2) 566 mpfr_set_overflow (); 567 else 568 mpfr_clear_overflow (); 569 /* the divide-by-0 flag was added in MPFR 3.1.0 */ 570#ifdef mpfr_set_divby0 571 if (counter & 4) 572 mpfr_set_divby0 (); 573 else 574 mpfr_clear_divby0 (); 575#endif 576 if (counter & 8) 577 mpfr_set_nanflag (); 578 else 579 mpfr_clear_nanflag (); 580 if (counter & 16) 581 mpfr_set_inexflag (); 582 else 583 mpfr_clear_inexflag (); 584 if (counter & 32) 585 mpfr_set_erangeflag (); 586 else 587 mpfr_clear_erangeflag (); 588} 589 590/* Check MPFR flags: we allow that some flags are set internally by MPC, 591 for example if MPC does internal computations (using MPFR) which yield 592 an overflow, even if the final MPC result fits in the exponent range. 593 However we don't allow MPC to *clear* the MPFR flags */ 594static void 595check_mpfr_flags (int counter) 596{ 597 int old, neu; 598 599 old = (counter & 1) != 0; 600 neu = mpfr_underflow_p () != 0; 601 if (old && (neu == 0)) 602 { 603 printf ("Error, underflow flag has been modified from %d to %d\n", 604 old, neu); 605 exit (1); 606 } 607 old = (counter & 2) != 0; 608 neu = mpfr_overflow_p () != 0; 609 if (old && (neu == 0)) 610 { 611 printf ("Error, overflow flag has been modified from %d to %d\n", 612 old, neu); 613 exit (1); 614 } 615#ifdef mpfr_divby0_p 616 old = (counter & 4) != 0; 617 neu = mpfr_divby0_p () != 0; 618 if (old && (neu == 0)) 619 { 620 printf ("Error, divby0 flag has been modified from %d to %d\n", 621 old, neu); 622 exit (1); 623 } 624#endif 625 old = (counter & 8) != 0; 626 neu = mpfr_nanflag_p () != 0; 627 if (old && (neu == 0)) 628 { 629 printf ("Error, nanflag flag has been modified from %d to %d\n", 630 old, neu); 631 exit (1); 632 } 633 old = (counter & 16) != 0; 634 neu = mpfr_inexflag_p () != 0; 635 if (old && (neu == 0)) 636 { 637 printf ("Error, inexflag flag has been modified from %d to %d\n", 638 old, neu); 639 exit (1); 640 } 641 old = (counter & 32) != 0; 642 neu = mpfr_erangeflag_p () != 0; 643 if (old && (neu == 0)) 644 { 645 printf ("Error, erangeflag flag has been modified from %d to %d\n", 646 old, neu); 647 exit (1); 648 } 649} 650 651/* data_check (function, data_file_name) checks function results against 652 precomputed data in a file.*/ 653void 654data_check (mpc_function function, const char *file_name) 655{ 656 FILE *fp; 657 658 int inex_re; 659 mpfr_t x1, x2; 660 mpfr_rnd_t mpfr_rnd = GMP_RNDN; 661 int sign_real; 662 663 int inex_im; 664 mpc_t z1, z2, z3, z4, z5; 665 mpc_rnd_t rnd = MPC_RNDNN; 666 667 unsigned long int ui; 668 long int si; 669 670 known_signs_t signs; 671 int inex = 0; 672 673 static int rand_counter = 0; 674 675 fp = open_data_file (file_name); 676 677 /* 1. init needed variables */ 678 mpc_init2 (z1, 2); 679 switch (function.type) 680 { 681 case FC: 682 mpfr_init (x1); 683 mpfr_init (x2); 684 break; 685 case CC: case CCU: case CCS: 686 mpc_init2 (z2, 2); 687 mpc_init2 (z3, 2); 688 break; 689 case C_CC: 690 mpc_init2 (z2, 2); 691 mpc_init2 (z3, 2); 692 mpc_init2 (z4, 2); 693 break; 694 case CCCC: 695 mpc_init2 (z2, 2); 696 mpc_init2 (z3, 2); 697 mpc_init2 (z4, 2); 698 mpc_init2 (z5, 2); 699 break; 700 case CFC: case CCF: 701 mpfr_init (x1); 702 mpc_init2 (z2, 2); 703 mpc_init2 (z3, 2); 704 break; 705 default: 706 ; 707 } 708 709 /* 2. read data file */ 710 line_number = 1; 711 nextchar = getc (fp); 712 skip_whitespace_comments (fp); 713 while (nextchar != EOF) { 714 set_mpfr_flags (rand_counter); 715 716 /* for each kind of function prototype: */ 717 /* 3.1 read a line of data: expected result, parameters, rounding mode */ 718 /* 3.2 compute function at the same precision as the expected result */ 719 /* 3.3 compare this result with the expected one */ 720 switch (function.type) 721 { 722 case FC: /* example mpc_norm */ 723 read_fc (fp, &inex_re, x1, &sign_real, z1, &mpfr_rnd); 724 mpfr_set_prec (x2, mpfr_get_prec (x1)); 725 inex = function.pointer.FC (x2, z1, mpfr_rnd); 726 if ((inex_re != TERNARY_NOT_CHECKED && inex_re != inex) 727 || !same_mpfr_value (x1, x2, sign_real)) 728 { 729 mpfr_t got, expected; 730 mpc_t op; 731 op[0] = z1[0]; 732 got[0] = x2[0]; 733 expected[0] = x1[0]; 734 printf ("%s(op) failed (%s:%lu)\nwith rounding mode %s\n", 735 function.name, file_name, test_line_number, 736 mpfr_rnd_mode[mpfr_rnd]); 737 if (inex_re != TERNARY_NOT_CHECKED && inex_re != inex) 738 printf("ternary value: got %s, expected %s\n", 739 MPFR_INEX_STR (inex), MPFR_INEX_STR (inex_re)); 740 MPC_OUT (op); 741 printf (" "); 742 MPFR_OUT (got); 743 MPFR_OUT (expected); 744 745 exit (1); 746 } 747 break; 748 749 case CC: /* example mpc_log */ 750 read_cc (fp, &inex_re, &inex_im, z1, &signs, z2, &rnd); 751 mpfr_set_prec (mpc_realref (z3), MPC_PREC_RE (z1)); 752 mpfr_set_prec (mpc_imagref (z3), MPC_PREC_IM (z1)); 753 inex = function.pointer.CC (z3, z2, rnd); 754 if (!MPC_INEX_CMP (inex_re, inex_im, inex) 755 || !same_mpc_value (z3, z1, signs)) 756 { 757 mpc_t op, got, expected; /* display sensible variable names */ 758 op[0] = z2[0]; 759 expected[0]= z1[0]; 760 got[0] = z3[0]; 761 printf ("%s(op) failed (line %lu)\nwith rounding mode %s\n", 762 function.name, test_line_number, rnd_mode[rnd]); 763 if (!MPC_INEX_CMP (inex_re, inex_im, inex)) 764 printf("ternary value: got %s, expected (%s, %s)\n", 765 MPC_INEX_STR (inex), 766 MPFR_INEX_STR (inex_re), MPFR_INEX_STR (inex_im)); 767 MPC_OUT (op); 768 printf (" "); 769 MPC_OUT (got); 770 MPC_OUT (expected); 771 772 exit (1); 773 } 774 break; 775 776 case C_CC: /* example mpc_mul */ 777 read_ccc (fp, &inex_re, &inex_im, z1, &signs, z2, z3, &rnd); 778 mpfr_set_prec (mpc_realref(z4), MPC_PREC_RE (z1)); 779 mpfr_set_prec (mpc_imagref(z4), MPC_PREC_IM (z1)); 780 inex = function.pointer.C_CC (z4, z2, z3, rnd); 781 if (!MPC_INEX_CMP (inex_re, inex_im, inex) 782 || !same_mpc_value (z4, z1, signs)) 783 { 784 /* display sensible variable names */ 785 mpc_t op1, op2, got, expected; 786 op1[0] = z2[0]; 787 op2[0] = z3[0]; 788 expected[0]= z1[0]; 789 got[0] = z4[0]; 790 printf ("%s(op) failed (line %lu)\nwith rounding mode %s\n", 791 function.name, test_line_number, rnd_mode[rnd]); 792 if (!MPC_INEX_CMP (inex_re, inex_im, inex)) 793 printf("ternary value: got %s, expected (%s, %s)\n", 794 MPC_INEX_STR (inex), 795 MPFR_INEX_STR (inex_re), MPFR_INEX_STR (inex_im)); 796 MPC_OUT (op1); 797 MPC_OUT (op2); 798 printf (" "); 799 MPC_OUT (got); 800 MPC_OUT (expected); 801 802 exit (1); 803 } 804 if (function.properties & FUNC_PROP_SYMETRIC) 805 { 806 inex = function.pointer.C_CC (z4, z3, z2, rnd); 807 if (!MPC_INEX_CMP (inex_re, inex_im, inex) 808 || !same_mpc_value (z4, z1, signs)) 809 { 810 /* display sensible variable names */ 811 mpc_t op1, op2, got, expected; 812 op1[0] = z3[0]; 813 op2[0] = z2[0]; 814 expected[0]= z1[0]; 815 got[0] = z4[0]; 816 printf ("%s(op) failed (line %lu/symetric test)\n" 817 "with rounding mode %s\n", 818 function.name, test_line_number, rnd_mode[rnd]); 819 if (!MPC_INEX_CMP (inex_re, inex_im, inex)) 820 printf("ternary value: got %s, expected (%s, %s)\n", 821 MPC_INEX_STR (inex), 822 MPFR_INEX_STR (inex_re), MPFR_INEX_STR (inex_im)); 823 MPC_OUT (op1); 824 MPC_OUT (op2); 825 printf (" "); 826 MPC_OUT (got); 827 MPC_OUT (expected); 828 829 exit (1); 830 } 831 } 832 break; 833 834 case CCCC: /* example mpc_fma */ 835 read_cccc (fp, &inex_re, &inex_im, z1, &signs, z2, z3, z4, &rnd); 836 /* z1 is the expected value, z2, z3, z4 are the inputs, and z5 is 837 the computed value */ 838 mpfr_set_prec (mpc_realref(z5), MPC_PREC_RE (z1)); 839 mpfr_set_prec (mpc_imagref(z5), MPC_PREC_IM (z1)); 840 inex = function.pointer.CCCC (z5, z2, z3, z4, rnd); 841 if (!MPC_INEX_CMP (inex_re, inex_im, inex) 842 || !same_mpc_value (z5, z1, signs)) 843 { 844 /* display sensible variable names */ 845 mpc_t op1, op2, op3, got, expected; 846 op1[0] = z2[0]; 847 op2[0] = z3[0]; 848 op3[0] = z4[0]; 849 expected[0]= z1[0]; 850 got[0] = z5[0]; 851 printf ("%s(op) failed (line %lu)\nwith rounding mode %s\n", 852 function.name, test_line_number, rnd_mode[rnd]); 853 if (!MPC_INEX_CMP (inex_re, inex_im, inex)) 854 printf("ternary value: got %s, expected (%s, %s)\n", 855 MPC_INEX_STR (inex), 856 MPFR_INEX_STR (inex_re), MPFR_INEX_STR (inex_im)); 857 MPC_OUT (op1); 858 MPC_OUT (op2); 859 MPC_OUT (op3); 860 printf (" "); 861 MPC_OUT (got); 862 MPC_OUT (expected); 863 864 exit (1); 865 } 866 if (function.properties & FUNC_PROP_SYMETRIC) 867 { 868 inex = function.pointer.CCCC (z5, z3, z2, z4, rnd); 869 if (!MPC_INEX_CMP (inex_re, inex_im, inex) 870 || !same_mpc_value (z5, z1, signs)) 871 { 872 /* display sensible variable names */ 873 mpc_t op1, op2, op3, got, expected; 874 op1[0] = z3[0]; 875 op2[0] = z2[0]; 876 op3[0] = z4[0]; 877 expected[0]= z1[0]; 878 got[0] = z5[0]; 879 printf ("%s(op) failed (line %lu/symetric test)\n" 880 "with rounding mode %s\n", 881 function.name, test_line_number, rnd_mode[rnd]); 882 if (!MPC_INEX_CMP (inex_re, inex_im, inex)) 883 printf("ternary value: got %s, expected (%s, %s)\n", 884 MPC_INEX_STR (inex), 885 MPFR_INEX_STR (inex_re), MPFR_INEX_STR (inex_im)); 886 MPC_OUT (op1); 887 MPC_OUT (op2); 888 MPC_OUT (op3); 889 printf (" "); 890 MPC_OUT (got); 891 MPC_OUT (expected); 892 893 exit (1); 894 } 895 } 896 break; 897 898 case CFC: /* example mpc_fr_div */ 899 read_cfc (fp, &inex_re, &inex_im, z1, &signs, x1, z2, &rnd); 900 mpfr_set_prec (mpc_realref(z3), MPC_PREC_RE (z1)); 901 mpfr_set_prec (mpc_imagref(z3), MPC_PREC_IM (z1)); 902 inex = function.pointer.CFC (z3, x1, z2, rnd); 903 if (!MPC_INEX_CMP (inex_re, inex_im, inex) 904 || !same_mpc_value (z3, z1, signs)) 905 { 906 /* display sensible variable names */ 907 mpc_t op2, got, expected; 908 mpfr_t op1; 909 op1[0] = x1[0]; 910 op2[0] = z2[0]; 911 expected[0]= z1[0]; 912 got[0] = z3[0]; 913 printf ("%s(op) failed (line %lu)\nwith rounding mode %s\n", 914 function.name, test_line_number, rnd_mode[rnd]); 915 if (!MPC_INEX_CMP (inex_re, inex_im, inex)) 916 printf("ternary value: got %s, expected (%s, %s)\n", 917 MPC_INEX_STR (inex), 918 MPFR_INEX_STR (inex_re), MPFR_INEX_STR (inex_im)); 919 MPFR_OUT (op1); 920 MPC_OUT (op2); 921 printf (" "); 922 MPC_OUT (got); 923 MPC_OUT (expected); 924 925 exit (1); 926 } 927 break; 928 929 case CCF: /* example mpc_mul_fr */ 930 read_ccf (fp, &inex_re, &inex_im, z1, &signs, z2, x1, &rnd); 931 mpfr_set_prec (mpc_realref(z3), MPC_PREC_RE (z1)); 932 mpfr_set_prec (mpc_imagref(z3), MPC_PREC_IM (z1)); 933 inex = function.pointer.CCF (z3, z2, x1, rnd); 934 if (!MPC_INEX_CMP (inex_re, inex_im, inex) 935 || !same_mpc_value (z3, z1, signs)) 936 { 937 /* display sensible variable names */ 938 mpc_t op1, got, expected; 939 mpfr_t op2; 940 op1[0] = z2[0]; 941 op2[0] = x1[0]; 942 expected[0]= z1[0]; 943 got[0] = z3[0]; 944 printf ("%s(op) failed (line %lu)\nwith rounding mode %s\n", 945 function.name, test_line_number, rnd_mode[rnd]); 946 if (!MPC_INEX_CMP (inex_re, inex_im, inex)) 947 printf("ternary value: got %s, expected (%s, %s)\n", 948 MPC_INEX_STR (inex), 949 MPFR_INEX_STR (inex_re), MPFR_INEX_STR (inex_im)); 950 MPC_OUT (op1); 951 MPFR_OUT (op2); 952 printf (" "); 953 MPC_OUT (got); 954 MPC_OUT (expected); 955 956 exit (1); 957 } 958 break; 959 960 case CCU: /* example mpc_pow_ui */ 961 read_ccu (fp, &inex_re, &inex_im, z1, &signs, z2, &ui, &rnd); 962 mpfr_set_prec (mpc_realref(z3), MPC_PREC_RE (z1)); 963 mpfr_set_prec (mpc_imagref(z3), MPC_PREC_IM (z1)); 964 inex = function.pointer.CCU (z3, z2, ui, rnd); 965 if (!MPC_INEX_CMP (inex_re, inex_im, inex) 966 || !same_mpc_value (z3, z1, signs)) 967 { 968 /* display sensible variable names */ 969 mpc_t op1, got, expected; 970 op1[0] = z2[0]; 971 expected[0]= z1[0]; 972 got[0] = z3[0]; 973 printf ("%s(op) failed (line %lu)\nwith rounding mode %s\n", 974 function.name, test_line_number, rnd_mode[rnd]); 975 if (!MPC_INEX_CMP (inex_re, inex_im, inex)) 976 printf("ternary value: got %s, expected (%s, %s)\n", 977 MPC_INEX_STR (inex), 978 MPFR_INEX_STR (inex_re), MPFR_INEX_STR (inex_im)); 979 MPC_OUT (op1); 980 printf ("op2 %lu\n ", ui); 981 MPC_OUT (got); 982 MPC_OUT (expected); 983 984 exit (1); 985 } 986 break; 987 988 case CCS: /* example mpc_pow_si */ 989 read_ccs (fp, &inex_re, &inex_im, z1, &signs, z2, &si, &rnd); 990 mpfr_set_prec (mpc_realref(z3), MPC_PREC_RE (z1)); 991 mpfr_set_prec (mpc_imagref(z3), MPC_PREC_IM (z1)); 992 inex = function.pointer.CCS (z3, z2, si, rnd); 993 if (!MPC_INEX_CMP (inex_re, inex_im, inex) 994 || !same_mpc_value (z3, z1, signs)) 995 { 996 /* display sensible variable names */ 997 mpc_t op1, got, expected; 998 op1[0] = z2[0]; 999 expected[0]= z1[0]; 1000 got[0] = z3[0]; 1001 printf ("%s(op) failed (line %lu)\nwith rounding mode %s\n", 1002 function.name, test_line_number, rnd_mode[rnd]); 1003 if (!MPC_INEX_CMP (inex_re, inex_im, inex)) 1004 printf("ternary value: got %s, expected (%s, %s)\n", 1005 MPC_INEX_STR (inex), 1006 MPFR_INEX_STR (inex_re), MPFR_INEX_STR (inex_im)); 1007 MPC_OUT (op1); 1008 printf ("op2 %li\n ", si); 1009 MPC_OUT (got); 1010 MPC_OUT (expected); 1011 1012 exit (1); 1013 } 1014 break; 1015 1016 default: 1017 printf ("Unhandled function prototype %i in 'data_check'\n", function.type); 1018 exit (1); 1019 } 1020 1021 /* check MPFR flags were not modified */ 1022 check_mpfr_flags (rand_counter); 1023 rand_counter ++; 1024 } 1025 1026 /* 3. Clear used variables */ 1027 mpc_clear (z1); 1028 switch (function.type) 1029 { 1030 case FC: 1031 mpfr_clear (x1); 1032 mpfr_clear (x2); 1033 break; 1034 case CC: case CCU: case CCS: 1035 mpc_clear (z2); 1036 mpc_clear (z3); 1037 break; 1038 case C_CC: 1039 mpc_clear (z2); 1040 mpc_clear (z3); 1041 mpc_clear (z4); 1042 break; 1043 case CCCC: 1044 mpc_clear (z2); 1045 mpc_clear (z3); 1046 mpc_clear (z4); 1047 mpc_clear (z5); 1048 break; 1049 case CFC: case CCF: 1050 mpfr_clear (x1); 1051 mpc_clear (z2); 1052 mpc_clear (z3); 1053 break; 1054 default: 1055 ; 1056 } 1057 1058 close_data_file (fp); 1059} 1060