read_data.c revision 1.1 1 /* read_data,c -- Read data file and check function.
2
3 Copyright (C) 2008, 2009, 2010, 2011, 2012 INRIA
4
5 This file is part of GNU MPC.
6
7 GNU MPC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU Lesser General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11
12 GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15 more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along 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
25 char *pathname;
26 unsigned long line_number;
27 /* file name with complete path and currently read line;
28 kept globally to simplify parameter passing */
29 unsigned long test_line_number;
30 /* start line of data test (which may extend over several lines) */
31 int 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
43 static const char *mpfr_rnd_mode [] =
44 { "GMP_RNDN", "GMP_RNDZ", "GMP_RNDU", "GMP_RNDD" };
45
46 const 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 */
66 FILE *
67 open_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
94 void
95 close_data_file (FILE *fp)
96 {
97 free (pathname);
98 fclose (fp);
99 }
100
101 /* read primitives */
102 static void
103 skip_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
116 static void
117 skip_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
129 void
130 skip_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
142 size_t
143 read_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. */
205 void
206 read_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
235 void
236 read_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
268 void
269 read_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
277 void
278 read_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
301 static void
302 read_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
325 static void
326 read_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
349 mpfr_prec_t
350 read_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
375 static void
376 read_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
395 void
396 read_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
412 void
413 read_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
419 static void
420 check_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 */
437 static void
438 read_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
451 static void
452 read_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
463 static void
464 read_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 */
480 static void
481 read_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
497 static void
498 read_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
512 static void
513 read_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
527 static void
528 read_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
542 static void
543 read_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 */
558 static void
559 set_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 */
594 static void
595 check_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.*/
653 void
654 data_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