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
tpl_read_mpfr_prec(mpc_datafile_context_t * datafile_context)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
tpl_read_mpfr_mantissa(mpc_datafile_context_t * datafile_context,mpfr_ptr x)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
tpl_read_mpfr(mpc_datafile_context_t * datafile_context,mpfr_ptr x,int * known_sign)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
tpl_read_mpfr_rnd(mpc_datafile_context_t * datafile_context,mpfr_rnd_t * rnd)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
tpl_read_mpfr_inex(mpc_datafile_context_t * datafile_context,int * ternary)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
tpl_same_mpfr_value(mpfr_ptr x1,mpfr_ptr x2,int known_sign)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
tpl_check_mpfr_data(mpfr_t got,mpfr_data_t expected)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
tpl_copy_mpfr(mpfr_ptr dest,mpfr_srcptr src)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