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