xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tfrexp.c (revision ba125506a622fe649968631a56eba5d42ff57863)
1 /* Test file for mpfr_frexp.
2 
3 Copyright 2011-2023 Free Software Foundation, Inc.
4 Contributed by the AriC and Caramba projects, INRIA.
5 
6 This file is part of the GNU MPFR Library.
7 
8 The GNU MPFR Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 The GNU MPFR Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16 License for more details.
17 
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
20 https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22 
23 #include "mpfr-test.h"
24 
25 static void
check_special(void)26 check_special (void)
27 {
28   mpfr_t x, y;
29   int inex;
30   mpfr_exp_t exp;
31 
32   mpfr_init2 (x, 53);
33   mpfr_init2 (y, 53);
34 
35   mpfr_set_nan (x);
36   inex = mpfr_frexp (&exp, y, x, MPFR_RNDN);
37   if (mpfr_nan_p (y) == 0 || inex != 0)
38     {
39       printf ("Error for mpfr_frexp(NaN)\n");
40       exit (1);
41     }
42 
43   mpfr_set_inf (x, 1);
44   inex = mpfr_frexp (&exp, y, x, MPFR_RNDN);
45   if (mpfr_inf_p (y) == 0 || mpfr_sgn (y) <= 0 || inex != 0)
46     {
47       printf ("Error for mpfr_frexp(+Inf)\n");
48       exit (1);
49     }
50 
51   mpfr_set_inf (x, -1);
52   inex = mpfr_frexp (&exp, y, x, MPFR_RNDN);
53   if (mpfr_inf_p (y) == 0 || mpfr_sgn (y) >= 0 || inex != 0)
54     {
55       printf ("Error for mpfr_frexp(-Inf)\n");
56       exit (1);
57     }
58 
59   mpfr_set_zero (x, 1);
60   inex = mpfr_frexp (&exp, y, x, MPFR_RNDN);
61   if (mpfr_zero_p (y) == 0 || mpfr_signbit (y) != 0 || inex != 0 || exp != 0)
62     {
63       printf ("Error for mpfr_frexp(+0)\n");
64       exit (1);
65     }
66 
67   mpfr_set_zero (x, -1);
68   inex = mpfr_frexp (&exp, y, x, MPFR_RNDN);
69   if (mpfr_zero_p (y) == 0 || mpfr_signbit (y) == 0 || inex != 0 || exp != 0)
70     {
71       printf ("Error for mpfr_frexp(-0)\n");
72       exit (1);
73     }
74 
75   mpfr_set_ui (x, 17, MPFR_RNDN);
76   inex = mpfr_frexp (&exp, y, x, MPFR_RNDN);
77   /* 17 = 17/32*2^5 */
78   if (mpfr_cmp_ui_2exp (y, 17, -5) != 0 || inex != 0 || exp != 5)
79     {
80       printf ("Error for mpfr_frexp(17)\n");
81       exit (1);
82     }
83 
84   mpfr_set_si (x, -17, MPFR_RNDN);
85   inex = mpfr_frexp (&exp, y, x, MPFR_RNDN);
86   if (mpfr_cmp_si_2exp (y, -17, -5) != 0 || inex != 0 || exp != 5)
87     {
88       printf ("Error for mpfr_frexp(-17)\n");
89       exit (1);
90     }
91 
92   /* now reduce the precision of y */
93   mpfr_set_prec (y, 4);
94   mpfr_set_ui (x, 17, MPFR_RNDN);
95   inex = mpfr_frexp (&exp, y, x, MPFR_RNDN);
96   /* 17 -> 16/32*2^5 */
97   if (mpfr_cmp_ui_2exp (y, 16, -5) != 0 || inex >= 0 || exp != 5)
98     {
99       printf ("Error for mpfr_frexp(17) with prec=4, RNDN\n");
100       exit (1);
101     }
102 
103   mpfr_set_ui (x, 17, MPFR_RNDN);
104   inex = mpfr_frexp (&exp, y, x, MPFR_RNDZ);
105   if (mpfr_cmp_ui_2exp (y, 16, -5) != 0 || inex >= 0 || exp != 5)
106     {
107       printf ("Error for mpfr_frexp(17) with prec=4, RNDZ\n");
108       exit (1);
109     }
110 
111   mpfr_set_ui (x, 17, MPFR_RNDN);
112   inex = mpfr_frexp (&exp, y, x, MPFR_RNDD);
113   if (mpfr_cmp_ui_2exp (y, 16, -5) != 0 || inex >= 0 || exp != 5)
114     {
115       printf ("Error for mpfr_frexp(17) with prec=4, RNDD\n");
116       exit (1);
117     }
118 
119   mpfr_set_ui (x, 17, MPFR_RNDN);
120   inex = mpfr_frexp (&exp, y, x, MPFR_RNDU);
121   if (mpfr_cmp_ui_2exp (y, 18, -5) != 0 || inex <= 0 || exp != 5)
122     {
123       printf ("Error for mpfr_frexp(17) with prec=4, RNDU\n");
124       exit (1);
125     }
126 
127   mpfr_clear (y);
128   mpfr_clear (x);
129 }
130 
check1(void)131 static void check1 (void)
132 {
133   mpfr_exp_t emin, emax, e;
134   mpfr_t x, y1, y2;
135   int r, neg, red;
136 
137   emin = mpfr_get_emin ();
138   emax = mpfr_get_emax ();
139   set_emin (MPFR_EMIN_MIN);
140   set_emax (MPFR_EMAX_MAX);
141 
142   mpfr_init2 (x, 7);
143   mpfr_inits2 (4, y1, y2, (mpfr_ptr) 0);
144 
145   mpfr_set_ui_2exp (x, 1, -2, MPFR_RNDN);
146   while (mpfr_regular_p (x))
147     {
148       /* Test the exponents up to 3 and with the maximum exponent
149          (to check potential intermediate overflow). */
150       if (MPFR_GET_EXP (x) == 4)
151         mpfr_set_exp (x, MPFR_EMAX_MAX);
152       e = MPFR_GET_EXP (x);
153       for (neg = 0; neg < 2; neg++)
154         {
155           RND_LOOP (r)
156             {
157               int inex1, inex2;
158               mpfr_exp_t e1, e2;
159               mpfr_flags_t flags1, flags2;
160 
161               for (red = 0; red < 2; red++)
162                 {
163                   if (red)
164                     {
165                       /* e1: exponent of the rounded value of x. */
166                       MPFR_ASSERTN (e1 == e || e1 == e + 1);
167                       set_emin (e);
168                       set_emax (e);
169                       mpfr_clear_flags ();
170                       inex1 = e1 < 0 ?
171                         mpfr_mul_2ui (y1, x, -e1, (mpfr_rnd_t) r) :
172                         mpfr_div_2ui (y1, x, e1, (mpfr_rnd_t) r);
173                       flags1 = __gmpfr_flags;
174                     }
175                   else
176                     {
177                       inex1 = mpfr_set (y1, x, (mpfr_rnd_t) r);
178                       e1 = MPFR_IS_INF (y1) ? e + 1 : MPFR_GET_EXP (y1);
179                       flags1 = inex1 != 0 ? MPFR_FLAGS_INEXACT : 0;
180                     }
181                   mpfr_clear_flags ();
182                   inex2 = mpfr_frexp (&e2, y2, x, (mpfr_rnd_t) r);
183                   flags2 = __gmpfr_flags;
184                   set_emin (MPFR_EMIN_MIN);
185                   set_emax (MPFR_EMAX_MAX);
186                   if ((!red || e == 0) &&
187                       (! mpfr_regular_p (y2) || MPFR_GET_EXP (y2) != 0))
188                     {
189                       printf ("Error in check1 for %s, red = %d, x = ",
190                               mpfr_print_rnd_mode ((mpfr_rnd_t) r), red);
191                       mpfr_dump (x);
192                       printf ("Expected 1/2 <= |y| < 1, got y = ");
193                       mpfr_dump (y2);
194                       exit (1);
195                     }
196                   if (!red)
197                     {
198                       if (e2 > 0)
199                         mpfr_mul_2ui (y2, y2, e2, MPFR_RNDN);
200                       else if (e2 < 0)
201                         mpfr_div_2ui (y2, y2, -e2, MPFR_RNDN);
202                     }
203                   if (! (SAME_SIGN (inex1, inex2) &&
204                          mpfr_equal_p (y1, y2) &&
205                          flags1 == flags2))
206                     {
207                       printf ("Error in check1 for %s, red = %d, x = ",
208                               mpfr_print_rnd_mode ((mpfr_rnd_t) r), red);
209                       mpfr_dump (x);
210                       printf ("Expected y1 = ");
211                       mpfr_dump (y1);
212                       printf ("Got      y2 = ");
213                       mpfr_dump (y2);
214                       printf ("Expected inex ~= %d, got %d\n", inex1, inex2);
215                       printf ("Expected flags:");
216                       flags_out (flags1);
217                       printf ("Got flags:     ");
218                       flags_out (flags2);
219                       exit (1);
220                     }
221                 }
222             }
223           mpfr_neg (x, x, MPFR_RNDN);
224         }
225       mpfr_nextabove (x);
226     }
227 
228   mpfr_clears (x, y1, y2, (mpfr_ptr) 0);
229   set_emin (emin);
230   set_emax (emax);
231 }
232 
233 int
main(int argc,char * argv[])234 main (int argc, char *argv[])
235 {
236   tests_start_mpfr ();
237 
238   check_special ();
239   check1 ();
240 
241   tests_end_mpfr ();
242   return 0;
243 }
244