Imported Upstream version 1.0
[platform/upstream/mpc.git] / tests / read_data.c
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 }