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