Home | History | Annotate | Line # | Download | only in tests
      1  1.1.1.2  mrg /* read_data.c -- Read data file and check function.
      2      1.1  mrg 
      3  1.1.1.3  mrg Copyright (C) 2008, 2009, 2010, 2011, 2012, 2022 INRIA
      4      1.1  mrg 
      5      1.1  mrg This file is part of GNU MPC.
      6      1.1  mrg 
      7      1.1  mrg GNU MPC is free software; you can redistribute it and/or modify it under
      8      1.1  mrg the terms of the GNU Lesser General Public License as published by the
      9      1.1  mrg Free Software Foundation; either version 3 of the License, or (at your
     10      1.1  mrg option) any later version.
     11      1.1  mrg 
     12      1.1  mrg GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY
     13      1.1  mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
     14      1.1  mrg FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
     15      1.1  mrg more details.
     16      1.1  mrg 
     17      1.1  mrg You should have received a copy of the GNU Lesser General Public License
     18      1.1  mrg along with this program. If not, see http://www.gnu.org/licenses/ .
     19      1.1  mrg */
     20      1.1  mrg 
     21      1.1  mrg #include <stdlib.h>
     22      1.1  mrg #include <string.h>
     23      1.1  mrg #include "mpc-tests.h"
     24      1.1  mrg 
     25      1.1  mrg char *pathname;
     26      1.1  mrg unsigned long line_number;
     27      1.1  mrg    /* file name with complete path and currently read line;
     28      1.1  mrg       kept globally to simplify parameter passing */
     29      1.1  mrg unsigned long test_line_number;
     30      1.1  mrg    /* start line of data test (which may extend over several lines) */
     31      1.1  mrg int nextchar;
     32      1.1  mrg    /* character appearing next in the file, may be EOF */
     33      1.1  mrg 
     34      1.1  mrg #define MPC_INEX_CMP(r, i, c)                                 \
     35      1.1  mrg   (((r) == TERNARY_NOT_CHECKED || (r) == MPC_INEX_RE(c))      \
     36      1.1  mrg    && ((i) == TERNARY_NOT_CHECKED || (i) == MPC_INEX_IM (c)))
     37      1.1  mrg 
     38      1.1  mrg #define MPFR_INEX_STR(inex)                     \
     39      1.1  mrg   (inex) == TERNARY_NOT_CHECKED ? "?"           \
     40      1.1  mrg     : (inex) == +1 ? "+1"                       \
     41      1.1  mrg     : (inex) == -1 ? "-1" : "0"
     42      1.1  mrg 
     43      1.1  mrg /* file functions */
     44      1.1  mrg FILE *
     45      1.1  mrg open_data_file (const char *file_name)
     46      1.1  mrg {
     47      1.1  mrg   FILE *fp;
     48      1.1  mrg   char *src_dir;
     49      1.1  mrg   char default_srcdir[] = ".";
     50      1.1  mrg 
     51      1.1  mrg   src_dir = getenv ("srcdir");
     52      1.1  mrg   if (src_dir == NULL)
     53      1.1  mrg     src_dir = default_srcdir;
     54      1.1  mrg 
     55      1.1  mrg   pathname = (char *) malloc ((strlen (src_dir)) + strlen (file_name) + 2);
     56      1.1  mrg   if (pathname == NULL)
     57      1.1  mrg     {
     58      1.1  mrg       printf ("Cannot allocate memory\n");
     59      1.1  mrg       exit (1);
     60      1.1  mrg     }
     61      1.1  mrg   sprintf (pathname, "%s/%s", src_dir, file_name);
     62      1.1  mrg   fp = fopen (pathname, "r");
     63      1.1  mrg   if (fp == NULL)
     64      1.1  mrg     {
     65      1.1  mrg       fprintf (stderr, "Unable to open %s\n", pathname);
     66      1.1  mrg       exit (1);
     67      1.1  mrg     }
     68      1.1  mrg 
     69      1.1  mrg   return fp;
     70      1.1  mrg }
     71      1.1  mrg 
     72      1.1  mrg void
     73      1.1  mrg close_data_file (FILE *fp)
     74      1.1  mrg {
     75      1.1  mrg   free (pathname);
     76      1.1  mrg   fclose (fp);
     77      1.1  mrg }
     78      1.1  mrg 
     79      1.1  mrg /* read primitives */
     80      1.1  mrg static void
     81      1.1  mrg skip_line (FILE *fp)
     82      1.1  mrg    /* skips characters until reaching '\n' or EOF; */
     83      1.1  mrg    /* '\n' is skipped as well                      */
     84      1.1  mrg {
     85      1.1  mrg    while (nextchar != EOF && nextchar != '\n')
     86      1.1  mrg      nextchar = getc (fp);
     87      1.1  mrg    if (nextchar != EOF)
     88      1.1  mrg      {
     89      1.1  mrg        line_number ++;
     90      1.1  mrg        nextchar = getc (fp);
     91      1.1  mrg      }
     92      1.1  mrg }
     93      1.1  mrg 
     94      1.1  mrg static void
     95      1.1  mrg skip_whitespace (FILE *fp)
     96      1.1  mrg    /* skips over whitespace if any until reaching EOF */
     97      1.1  mrg    /* or non-whitespace                               */
     98      1.1  mrg {
     99      1.1  mrg    while (isspace (nextchar))
    100      1.1  mrg      {
    101      1.1  mrg        if (nextchar == '\n')
    102      1.1  mrg          line_number ++;
    103      1.1  mrg        nextchar = getc (fp);
    104      1.1  mrg      }
    105      1.1  mrg }
    106      1.1  mrg 
    107      1.1  mrg void
    108      1.1  mrg skip_whitespace_comments (FILE *fp)
    109      1.1  mrg    /* skips over all whitespace and comments, if any */
    110      1.1  mrg {
    111      1.1  mrg    skip_whitespace (fp);
    112      1.1  mrg    while (nextchar == '#') {
    113      1.1  mrg       skip_line (fp);
    114      1.1  mrg       if (nextchar != EOF)
    115      1.1  mrg          skip_whitespace (fp);
    116      1.1  mrg    }
    117      1.1  mrg }
    118      1.1  mrg 
    119      1.1  mrg size_t
    120      1.1  mrg read_string (FILE *fp, char **buffer_ptr, size_t buffer_length, const char *name)
    121      1.1  mrg {
    122      1.1  mrg   size_t pos;
    123      1.1  mrg   char *buffer;
    124      1.1  mrg 
    125      1.1  mrg   pos = 0;
    126      1.1  mrg   buffer = *buffer_ptr;
    127      1.1  mrg 
    128      1.1  mrg   if (nextchar == '"')
    129      1.1  mrg     nextchar = getc (fp);
    130      1.1  mrg   else
    131      1.1  mrg     goto error;
    132      1.1  mrg 
    133      1.1  mrg   while (nextchar != EOF && nextchar != '"')
    134      1.1  mrg     {
    135      1.1  mrg       if (nextchar == '\n')
    136      1.1  mrg         line_number ++;
    137      1.1  mrg       if (pos + 1 > buffer_length)
    138      1.1  mrg         {
    139      1.1  mrg           buffer = (char *) realloc (buffer, 2 * buffer_length);
    140      1.1  mrg           if (buffer == NULL)
    141      1.1  mrg             {
    142      1.1  mrg               printf ("Cannot allocate memory\n");
    143      1.1  mrg               exit (1);
    144      1.1  mrg             }
    145      1.1  mrg           buffer_length *= 2;
    146      1.1  mrg         }
    147      1.1  mrg       buffer[pos++] = (char) nextchar;
    148      1.1  mrg       nextchar = getc (fp);
    149      1.1  mrg     }
    150      1.1  mrg 
    151      1.1  mrg   if (nextchar != '"')
    152      1.1  mrg     goto error;
    153      1.1  mrg 
    154      1.1  mrg   if (pos + 1 > buffer_length)
    155      1.1  mrg     {
    156      1.1  mrg       buffer = (char *) realloc (buffer, buffer_length + 1);
    157      1.1  mrg       if (buffer == NULL)
    158      1.1  mrg         {
    159      1.1  mrg           printf ("Cannot allocate memory\n");
    160      1.1  mrg           exit (1);
    161      1.1  mrg         }
    162      1.1  mrg       buffer_length *= 2;
    163      1.1  mrg     }
    164      1.1  mrg   buffer[pos] = '\0';
    165      1.1  mrg 
    166      1.1  mrg   nextchar = getc (fp);
    167      1.1  mrg   skip_whitespace_comments (fp);
    168      1.1  mrg 
    169      1.1  mrg   *buffer_ptr = buffer;
    170      1.1  mrg 
    171      1.1  mrg   return buffer_length;
    172      1.1  mrg 
    173      1.1  mrg  error:
    174      1.1  mrg   printf ("Error: Unable to read %s in file '%s' line '%lu'\n",
    175      1.1  mrg           name, pathname, line_number);
    176      1.1  mrg   exit (1);
    177      1.1  mrg }
    178      1.1  mrg 
    179      1.1  mrg /* All following read routines skip over whitespace and comments; */
    180      1.1  mrg /* so after calling them, nextchar is either EOF or the beginning */
    181      1.1  mrg /* of a non-comment token.                                        */
    182      1.1  mrg void
    183      1.1  mrg read_ternary (FILE *fp, int* ternary)
    184      1.1  mrg {
    185      1.1  mrg   switch (nextchar)
    186      1.1  mrg     {
    187      1.1  mrg     case '!':
    188      1.1  mrg       *ternary = TERNARY_ERROR;
    189      1.1  mrg       break;
    190      1.1  mrg     case '?':
    191      1.1  mrg       *ternary = TERNARY_NOT_CHECKED;
    192      1.1  mrg       break;
    193      1.1  mrg     case '+':
    194      1.1  mrg       *ternary = +1;
    195      1.1  mrg       break;
    196      1.1  mrg     case '0':
    197      1.1  mrg       *ternary = 0;
    198      1.1  mrg       break;
    199      1.1  mrg     case '-':
    200      1.1  mrg       *ternary = -1;
    201      1.1  mrg       break;
    202      1.1  mrg     default:
    203      1.1  mrg       printf ("Error: Unexpected ternary value '%c' in file '%s' line %lu\n",
    204      1.1  mrg               nextchar, pathname, line_number);
    205      1.1  mrg       exit (1);
    206      1.1  mrg     }
    207      1.1  mrg 
    208      1.1  mrg   nextchar = getc (fp);
    209      1.1  mrg   skip_whitespace_comments (fp);
    210      1.1  mrg }
    211      1.1  mrg 
    212      1.1  mrg void
    213      1.1  mrg read_mpfr_rounding_mode (FILE *fp, mpfr_rnd_t* rnd)
    214      1.1  mrg {
    215      1.1  mrg   switch (nextchar)
    216      1.1  mrg     {
    217      1.1  mrg     case 'n': case 'N':
    218  1.1.1.2  mrg       *rnd = MPFR_RNDN;
    219      1.1  mrg       break;
    220      1.1  mrg     case 'z': case 'Z':
    221  1.1.1.2  mrg       *rnd = MPFR_RNDZ;
    222      1.1  mrg       break;
    223      1.1  mrg     case 'u': case 'U':
    224  1.1.1.2  mrg       *rnd = MPFR_RNDU;
    225      1.1  mrg       break;
    226      1.1  mrg     case 'd': case 'D':
    227  1.1.1.2  mrg       *rnd = MPFR_RNDD;
    228      1.1  mrg       break;
    229  1.1.1.3  mrg     case 'a': case 'A':
    230  1.1.1.3  mrg       *rnd = MPFR_RNDA;
    231  1.1.1.3  mrg       break;
    232      1.1  mrg     default:
    233      1.1  mrg       printf ("Error: Unexpected rounding mode '%c' in file '%s' line %lu\n",
    234      1.1  mrg               nextchar, pathname, line_number);
    235      1.1  mrg       exit (1);
    236      1.1  mrg     }
    237      1.1  mrg 
    238      1.1  mrg     nextchar = getc (fp);
    239      1.1  mrg     if (nextchar != EOF && !isspace (nextchar)) {
    240      1.1  mrg       printf ("Error: Rounding mode not followed by white space in file "
    241      1.1  mrg               "'%s' line %lu\n",
    242      1.1  mrg               pathname, line_number);
    243      1.1  mrg       exit (1);
    244      1.1  mrg     }
    245      1.1  mrg     skip_whitespace_comments (fp);
    246      1.1  mrg }
    247      1.1  mrg 
    248      1.1  mrg void
    249      1.1  mrg read_mpc_rounding_mode (FILE *fp, mpc_rnd_t* rnd)
    250      1.1  mrg {
    251      1.1  mrg    mpfr_rnd_t re, im;
    252      1.1  mrg    read_mpfr_rounding_mode (fp, &re);
    253      1.1  mrg    read_mpfr_rounding_mode (fp, &im);
    254      1.1  mrg    *rnd = MPC_RND (re, im);
    255      1.1  mrg }
    256      1.1  mrg 
    257      1.1  mrg void
    258      1.1  mrg read_int (FILE *fp, int *nread, const char *name)
    259      1.1  mrg {
    260      1.1  mrg   int n = 0;
    261      1.1  mrg 
    262      1.1  mrg   if (nextchar == EOF)
    263      1.1  mrg     {
    264      1.1  mrg       printf ("Error: Unexpected EOF when reading int "
    265      1.1  mrg               "in file '%s' line %lu\n",
    266      1.1  mrg               pathname, line_number);
    267      1.1  mrg       exit (1);
    268      1.1  mrg     }
    269      1.1  mrg   ungetc (nextchar, fp);
    270      1.1  mrg   n = fscanf (fp, "%i", nread);
    271      1.1  mrg   if (ferror (fp) || n == 0 || n == EOF)
    272      1.1  mrg     {
    273      1.1  mrg       printf ("Error: Cannot read %s in file '%s' line %lu\n",
    274      1.1  mrg               name, pathname, line_number);
    275      1.1  mrg       exit (1);
    276      1.1  mrg     }
    277      1.1  mrg   nextchar = getc (fp);
    278      1.1  mrg   skip_whitespace_comments (fp);
    279      1.1  mrg }
    280      1.1  mrg 
    281      1.1  mrg mpfr_prec_t
    282      1.1  mrg read_mpfr_prec (FILE *fp)
    283      1.1  mrg {
    284      1.1  mrg    unsigned long prec;
    285      1.1  mrg    int n;
    286      1.1  mrg 
    287      1.1  mrg    if (nextchar == EOF) {
    288      1.1  mrg       printf ("Error: Unexpected EOF when reading mpfr precision "
    289      1.1  mrg               "in file '%s' line %lu\n",
    290      1.1  mrg               pathname, line_number);
    291      1.1  mrg       exit (1);
    292      1.1  mrg    }
    293      1.1  mrg    ungetc (nextchar, fp);
    294      1.1  mrg    n = fscanf (fp, "%lu", &prec);
    295      1.1  mrg    if (ferror (fp)) /* then also n == EOF */
    296      1.1  mrg       perror ("Error when reading mpfr precision");
    297      1.1  mrg    if (n == 0 || n == EOF || prec < MPFR_PREC_MIN || prec > MPFR_PREC_MAX) {
    298      1.1  mrg       printf ("Error: Impossible mpfr precision in file '%s' line %lu\n",
    299      1.1  mrg               pathname, line_number);
    300      1.1  mrg       exit (1);
    301      1.1  mrg    }
    302      1.1  mrg    nextchar = getc (fp);
    303      1.1  mrg    skip_whitespace_comments (fp);
    304      1.1  mrg    return (mpfr_prec_t) prec;
    305      1.1  mrg }
    306      1.1  mrg 
    307      1.1  mrg static void
    308      1.1  mrg read_mpfr_mantissa (FILE *fp, mpfr_ptr x)
    309      1.1  mrg {
    310      1.1  mrg    if (nextchar == EOF) {
    311      1.1  mrg       printf ("Error: Unexpected EOF when reading mpfr mantissa "
    312      1.1  mrg               "in file '%s' line %lu\n",
    313      1.1  mrg               pathname, line_number);
    314      1.1  mrg       exit (1);
    315      1.1  mrg    }
    316      1.1  mrg    ungetc (nextchar, fp);
    317  1.1.1.2  mrg    if (mpfr_inp_str (x, fp, 0, MPFR_RNDN) == 0) {
    318      1.1  mrg       printf ("Error: Impossible to read mpfr mantissa "
    319      1.1  mrg               "in file '%s' line %lu\n",
    320      1.1  mrg               pathname, line_number);
    321      1.1  mrg       exit (1);
    322      1.1  mrg    }
    323      1.1  mrg    nextchar = getc (fp);
    324      1.1  mrg    skip_whitespace_comments (fp);
    325      1.1  mrg }
    326      1.1  mrg 
    327      1.1  mrg void
    328      1.1  mrg read_mpfr (FILE *fp, mpfr_ptr x, int *known_sign)
    329      1.1  mrg {
    330      1.1  mrg    int sign;
    331      1.1  mrg    mpfr_set_prec (x, read_mpfr_prec (fp));
    332      1.1  mrg    sign = nextchar;
    333      1.1  mrg    read_mpfr_mantissa (fp, x);
    334      1.1  mrg 
    335      1.1  mrg    /* the sign always matters for regular values ('+' is implicit),
    336      1.1  mrg       but when no sign appears before 0 or Inf in the data file, it means
    337      1.1  mrg       that only absolute value must be checked. */
    338      1.1  mrg    if (known_sign != NULL)
    339      1.1  mrg      *known_sign =
    340      1.1  mrg        (!mpfr_zero_p (x) && !mpfr_inf_p (x))
    341      1.1  mrg        || sign == '+' || sign == '-';
    342      1.1  mrg }
    343      1.1  mrg 
    344      1.1  mrg void
    345      1.1  mrg read_mpc (FILE *fp, mpc_ptr z, known_signs_t *ks)
    346      1.1  mrg {
    347      1.1  mrg   read_mpfr (fp, mpc_realref (z), ks == NULL ? NULL : &ks->re);
    348      1.1  mrg   read_mpfr (fp, mpc_imagref (z), ks == NULL ? NULL : &ks->im);
    349      1.1  mrg }
    350