1 /* tpl_mpfr.c -- Helper functions for mpfr data. 2 3 Copyright (C) 2012, 2013, 2022 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 "mpc-tests.h" 22 23 static mpfr_prec_t 24 tpl_read_mpfr_prec (mpc_datafile_context_t* datafile_context) 25 { 26 unsigned long prec; 27 int n; 28 29 if (datafile_context->nextchar == EOF) { 30 printf ("Error: Unexpected EOF when reading mpfr precision " 31 "in file '%s' line %lu\n", 32 datafile_context->pathname, datafile_context->line_number); 33 exit (1); 34 } 35 ungetc (datafile_context->nextchar, datafile_context->fd); 36 n = fscanf (datafile_context->fd, "%lu", &prec); 37 if (ferror (datafile_context->fd)) /* then also n == EOF */ 38 perror ("Error when reading mpfr precision"); 39 if (n == 0 || n == EOF || prec < MPFR_PREC_MIN || prec > MPFR_PREC_MAX) { 40 printf ("Error: Impossible mpfr precision in file '%s' line %lu\n", 41 datafile_context->pathname, datafile_context->line_number); 42 exit (1); 43 } 44 datafile_context->nextchar = getc (datafile_context->fd); 45 tpl_skip_whitespace_comments (datafile_context); 46 return (mpfr_prec_t) prec; 47 } 48 49 static void 50 tpl_read_mpfr_mantissa (mpc_datafile_context_t* datafile_context, mpfr_ptr x) 51 { 52 if (datafile_context->nextchar == EOF) { 53 printf ("Error: Unexpected EOF when reading mpfr mantissa " 54 "in file '%s' line %lu\n", 55 datafile_context->pathname, datafile_context->line_number); 56 exit (1); 57 } 58 ungetc (datafile_context->nextchar, datafile_context->fd); 59 if (mpfr_inp_str (x, datafile_context->fd, 0, MPFR_RNDN) == 0) { 60 printf ("Error: Impossible to read mpfr mantissa " 61 "in file '%s' line %lu\n", 62 datafile_context->pathname, datafile_context->line_number); 63 exit (1); 64 } 65 datafile_context->nextchar = getc (datafile_context->fd); 66 tpl_skip_whitespace_comments (datafile_context); 67 } 68 69 void 70 tpl_read_mpfr (mpc_datafile_context_t* datafile_context, mpfr_ptr x, 71 int* known_sign) 72 { 73 int sign; 74 mpfr_set_prec (x, tpl_read_mpfr_prec (datafile_context)); 75 sign = datafile_context->nextchar; 76 tpl_read_mpfr_mantissa (datafile_context, x); 77 78 /* the sign always matters for regular values ('+' is implicit), 79 but when no sign appears before 0 or Inf in the data file, it means 80 that only absolute value must be checked. */ 81 MPC_ASSERT(known_sign != NULL); 82 *known_sign = 83 (!mpfr_zero_p (x) && !mpfr_inf_p (x)) || sign == '+' || sign == '-'; 84 } 85 86 void 87 tpl_read_mpfr_rnd (mpc_datafile_context_t* datafile_context, mpfr_rnd_t* rnd) 88 { 89 switch (datafile_context->nextchar) 90 { 91 case 'n': case 'N': 92 *rnd = MPFR_RNDN; 93 break; 94 case 'z': case 'Z': 95 *rnd = MPFR_RNDZ; 96 break; 97 case 'u': case 'U': 98 *rnd = MPFR_RNDU; 99 break; 100 case 'd': case 'D': 101 *rnd = MPFR_RNDD; 102 break; 103 case 'a': case 'A': 104 *rnd = MPFR_RNDA; 105 break; 106 default: 107 printf ("Error: Unexpected rounding mode '%c' in file '%s' line %lu\n", 108 datafile_context->nextchar, 109 datafile_context->pathname, 110 datafile_context->line_number); 111 exit (1); 112 } 113 114 datafile_context->nextchar = getc (datafile_context->fd); 115 if (datafile_context->nextchar != EOF 116 && !isspace (datafile_context->nextchar)) { 117 printf ("Error: Rounding mode not followed by white space " 118 "in file '%s' line %lu\n", 119 datafile_context->pathname, datafile_context->line_number); 120 exit (1); 121 } 122 tpl_skip_whitespace_comments (datafile_context); 123 } 124 125 126 void 127 tpl_read_mpfr_inex (mpc_datafile_context_t* datafile_context, int *ternary) 128 { 129 tpl_read_ternary(datafile_context, ternary); 130 } 131 132 int 133 tpl_same_mpfr_value (mpfr_ptr x1, mpfr_ptr x2, int known_sign) 134 { 135 /* The sign of zeroes and infinities is checked only when known_sign is 136 true. */ 137 if (mpfr_nan_p (x1)) 138 return mpfr_nan_p (x2); 139 if (mpfr_inf_p (x1)) 140 return mpfr_inf_p (x2) && 141 (!known_sign || mpfr_signbit (x1) == mpfr_signbit (x2)); 142 if (mpfr_zero_p (x1)) 143 return mpfr_zero_p (x2) && 144 (!known_sign || mpfr_signbit (x1) == mpfr_signbit (x2)); 145 return mpfr_cmp (x1, x2) == 0; 146 } 147 148 int 149 tpl_check_mpfr_data (mpfr_t got, mpfr_data_t expected) 150 { 151 return tpl_same_mpfr_value (got, expected.mpfr, expected.known_sign); 152 } 153 154 void 155 tpl_copy_mpfr (mpfr_ptr dest, mpfr_srcptr src) 156 { 157 /* source and destination are assumed to be of the same precision , so the 158 copy is exact (no rounding) */ 159 MPC_ASSERT(mpfr_get_prec (dest) == mpfr_get_prec (src)); 160 mpfr_set (dest, src, MPFR_RNDN); 161 } 162