xref: /netbsd-src/external/lgpl3/mpc/dist/tests/tpl_mpfr.c (revision 367b82799ab709709d3c3b541df56a2a14644d3e)
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