1 /* Test file for mpfr_exp2.
2
3 Copyright 2001-2004, 2006-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 #define TEST_FUNCTION mpfr_exp2
26 #define TEST_RANDOM_EMIN -36
27 #define TEST_RANDOM_EMAX 36
28 #include "tgeneric.c"
29
30 static void
special_overflow(void)31 special_overflow (void)
32 {
33 mpfr_t x, y;
34 int inex;
35 mpfr_exp_t emin, emax;
36
37 emin = mpfr_get_emin ();
38 emax = mpfr_get_emax ();
39
40 set_emin (-125);
41 set_emax (128);
42
43 mpfr_init2 (x, 24);
44 mpfr_init2 (y, 24);
45
46 mpfr_set_str_binary (x, "0.101100100000000000110100E15");
47 inex = mpfr_exp2 (y, x, MPFR_RNDN);
48 if (!mpfr_inf_p (y) || inex <= 0)
49 {
50 printf ("Overflow error.\n");
51 mpfr_dump (y);
52 printf ("inex = %d\n", inex);
53 exit (1);
54 }
55
56 mpfr_clear (y);
57 mpfr_clear (x);
58 set_emin (emin);
59 set_emax (emax);
60 }
61
62 static void
emax_m_eps(void)63 emax_m_eps (void)
64 {
65 if (mpfr_get_emax () <= LONG_MAX)
66 {
67 mpfr_t x, y;
68 int inex, ov;
69
70 mpfr_init2 (x, sizeof(mpfr_exp_t) * CHAR_BIT * 4);
71 mpfr_init2 (y, 8);
72 mpfr_set_si (x, mpfr_get_emax (), MPFR_RNDN);
73
74 mpfr_clear_flags ();
75 inex = mpfr_exp2 (y, x, MPFR_RNDN);
76 ov = mpfr_overflow_p ();
77 if (!ov || !mpfr_inf_p (y) || inex <= 0)
78 {
79 printf ("Overflow error for x = emax, MPFR_RNDN.\n");
80 mpfr_dump (y);
81 printf ("inex = %d, %soverflow\n", inex, ov ? "" : "no ");
82 exit (1);
83 }
84
85 mpfr_nextbelow (x);
86
87 mpfr_clear_flags ();
88 inex = mpfr_exp2 (y, x, MPFR_RNDN);
89 ov = mpfr_overflow_p ();
90 if (!ov || !mpfr_inf_p (y) || inex <= 0)
91 {
92 printf ("Overflow error for x = emax - eps, MPFR_RNDN.\n");
93 mpfr_dump (y);
94 printf ("inex = %d, %soverflow\n", inex, ov ? "" : "no ");
95 exit (1);
96 }
97
98 mpfr_clear_flags ();
99 inex = mpfr_exp2 (y, x, MPFR_RNDD);
100 ov = mpfr_overflow_p ();
101 if (ov || mpfr_inf_p (y) || inex >= 0 ||
102 (mpfr_nextabove (y), !mpfr_inf_p (y)))
103 {
104 printf ("Overflow error for x = emax - eps, MPFR_RNDD.\n");
105 mpfr_dump (y);
106 printf ("inex = %d, %soverflow\n", inex, ov ? "" : "no ");
107 exit (1);
108 }
109
110 mpfr_clear (x);
111 mpfr_clear (y);
112 }
113 }
114
115 static void
exp_range(void)116 exp_range (void)
117 {
118 mpfr_t x;
119 mpfr_exp_t emin;
120
121 emin = mpfr_get_emin ();
122 set_emin (3);
123 mpfr_init2 (x, 8);
124 mpfr_set_ui (x, 5, MPFR_RNDN);
125 mpfr_exp2 (x, x, MPFR_RNDN);
126 set_emin (emin);
127 if (mpfr_nan_p (x) || mpfr_cmp_ui (x, 32) != 0)
128 {
129 printf ("Error in mpfr_exp2 for x = 5, with emin = 3\n");
130 printf ("Expected 32, got ");
131 mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN);
132 printf ("\n");
133 exit (1);
134 }
135 mpfr_clear (x);
136 }
137
138 static void
overflowed_exp2_0(void)139 overflowed_exp2_0 (void)
140 {
141 mpfr_t x, y;
142 int emax, i, inex, rnd, err = 0;
143 mpfr_exp_t old_emax;
144
145 old_emax = mpfr_get_emax ();
146
147 mpfr_init2 (x, 8);
148 mpfr_init2 (y, 8);
149
150 for (emax = -1; emax <= 0; emax++)
151 {
152 mpfr_set_ui_2exp (y, 1, emax, MPFR_RNDN);
153 mpfr_nextbelow (y);
154 set_emax (emax); /* 1 is not representable. */
155 /* and if emax < 0, 1 - eps is not representable either. */
156 for (i = -1; i <= 1; i++)
157 RND_LOOP (rnd)
158 {
159 mpfr_set_si_2exp (x, i, -512 * ABS (i), MPFR_RNDN);
160 mpfr_clear_flags ();
161 inex = mpfr_exp2 (x, x, (mpfr_rnd_t) rnd);
162 if ((i >= 0 || emax < 0 || rnd == MPFR_RNDN || rnd == MPFR_RNDU) &&
163 ! mpfr_overflow_p ())
164 {
165 printf ("Error in overflowed_exp2_0 (i = %d, rnd = %s):\n"
166 " The overflow flag is not set.\n",
167 i, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
168 err = 1;
169 }
170 if (rnd == MPFR_RNDZ || rnd == MPFR_RNDD)
171 {
172 if (inex >= 0)
173 {
174 printf ("Error in overflowed_exp2_0 (i = %d, rnd = %s):\n"
175 " The inexact value must be negative.\n",
176 i, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
177 err = 1;
178 }
179 if (! mpfr_equal_p (x, y))
180 {
181 printf ("Error in overflowed_exp2_0 (i = %d, rnd = %s):\n"
182 " Got ", i,
183 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
184 mpfr_dump (x);
185 printf (" instead of 0.11111111E%d.\n", emax);
186 err = 1;
187 }
188 }
189 else if (rnd != MPFR_RNDF)
190 {
191 if (inex <= 0)
192 {
193 printf ("Error in overflowed_exp2_0 (i = %d, rnd = %s):\n"
194 " The inexact value must be positive.\n",
195 i, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
196 err = 1;
197 }
198 if (! (mpfr_inf_p (x) && MPFR_IS_POS (x)))
199 {
200 printf ("Error in overflowed_exp2_0 (i = %d, rnd = %s):\n"
201 " Got ", i,
202 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
203 mpfr_dump (x);
204 printf (" instead of +Inf.\n");
205 err = 1;
206 }
207 }
208 }
209 set_emax (old_emax);
210 }
211
212 if (err)
213 exit (1);
214 mpfr_clear (x);
215 mpfr_clear (y);
216 }
217
218 static void
bug20171218(void)219 bug20171218 (void)
220 {
221 mpfr_t x, y, z;
222 mpfr_exp_t emin;
223 int inex, i;
224 mpfr_flags_t flags, ex_flags;
225
226 emin = mpfr_get_emin ();
227
228 mpfr_init2 (x, 228);
229 mpfr_init2 (y, 11);
230 mpfr_init2 (z, 11);
231 mpfr_set_str_binary (x, "-0.110111010100001100000000000000111001100101011011101110101011000011011011001101111111110100110001110100111000111101010010100010001101100001010111101110100010000101011111001101011000011101000000001010001011110011110101010111000000E17");
232 set_emin (-113285);
233 mpfr_clear_flags ();
234 inex = mpfr_exp2 (y, x, MPFR_RNDA);
235 /* exact result is 0.11111111111110110000001011...E-113286, which rounded away
236 gives 0.10000000000E-113285, i.e., no underflow (after rounding) */
237 mpfr_set_str_binary (z, "0.10000000000E-113285");
238 MPFR_ASSERTN(mpfr_equal_p (y, z));
239 MPFR_ASSERTN(inex > 0);
240 MPFR_ASSERTN(mpfr_inexflag_p ());
241 MPFR_ASSERTN(!mpfr_underflow_p ());
242 mpfr_clear (x);
243 mpfr_clear (y);
244 mpfr_clear (z);
245
246 mpfr_init2 (x, 256);
247 mpfr_init2 (y, 8);
248 mpfr_init2 (z, 8);
249
250 for (i = 0; i < 3; i++)
251 {
252 set_emin (i == 0 ? -17 : i == 1 ? emin : MPFR_EMIN_MIN);
253 mpfr_set_exp_t (x, __gmpfr_emin - 2, MPFR_RNDN);
254 mpfr_nextabove (x);
255 mpfr_set_ui_2exp (z, 1, __gmpfr_emin - 1, MPFR_RNDN);
256 ex_flags = MPFR_FLAGS_UNDERFLOW | MPFR_FLAGS_INEXACT;
257 mpfr_clear_flags ();
258 inex = mpfr_exp2 (y, x, MPFR_RNDN);
259 flags = __gmpfr_flags;
260 if (! (flags == ex_flags && SAME_SIGN (inex, 1) && mpfr_equal_p (y, z)))
261 {
262 printf ("Error in bug20171218 for i=%d\n", i);
263 printf ("Expected ");
264 mpfr_dump (z);
265 printf (" with inex = 1 and flags:");
266 flags_out (ex_flags);
267 printf ("Got ");
268 mpfr_dump (y);
269 printf (" with inex = %d and flags:", inex);
270 flags_out (flags);
271 exit (1);
272 }
273 }
274
275 mpfr_clear (x);
276 mpfr_clear (y);
277 mpfr_clear (z);
278
279 set_emin (emin);
280 }
281
282 int
main(int argc,char * argv[])283 main (int argc, char *argv[])
284 {
285 mpfr_t x, y;
286 mpfr_exp_t emin, emax;
287
288 tests_start_mpfr ();
289
290 bug20171218 ();
291 special_overflow ();
292 emax_m_eps ();
293 exp_range ();
294
295 mpfr_init (x);
296 mpfr_init (y);
297
298 mpfr_set_ui (x, 4, MPFR_RNDN);
299 mpfr_exp2 (y, x, MPFR_RNDN);
300 if (mpfr_cmp_ui (y, 16) != 0)
301 {
302 printf ("Error for 2^4, MPFR_RNDN\n");
303 exit (1);
304 }
305 mpfr_exp2 (y, x, MPFR_RNDD);
306 if (mpfr_cmp_ui (y, 16) != 0)
307 {
308 printf ("Error for 2^4, MPFR_RNDD\n");
309 exit (1);
310 }
311 mpfr_exp2 (y, x, MPFR_RNDU);
312 if (mpfr_cmp_ui (y, 16) != 0)
313 {
314 printf ("Error for 2^4, MPFR_RNDU\n");
315 exit (1);
316 }
317
318 mpfr_set_si (x, -4, MPFR_RNDN);
319 mpfr_exp2 (y, x, MPFR_RNDN);
320 if (mpfr_cmp_ui_2exp (y, 1, -4) != 0)
321 {
322 printf ("Error for 2^(-4), MPFR_RNDN\n");
323 exit (1);
324 }
325 mpfr_exp2 (y, x, MPFR_RNDD);
326 if (mpfr_cmp_ui_2exp (y, 1, -4) != 0)
327 {
328 printf ("Error for 2^(-4), MPFR_RNDD\n");
329 exit (1);
330 }
331 mpfr_exp2 (y, x, MPFR_RNDU);
332 if (mpfr_cmp_ui_2exp (y, 1, -4) != 0)
333 {
334 printf ("Error for 2^(-4), MPFR_RNDU\n");
335 exit (1);
336 }
337
338 mpfr_set_prec (x, 53);
339 mpfr_set_prec (y, 53);
340 mpfr_set_str (x, /*-1683977482443233.0 / 2199023255552.0*/
341 "-7.6578429909351734750089235603809357e2", 10, MPFR_RNDN);
342 mpfr_exp2 (y, x, MPFR_RNDN);
343 if (mpfr_cmp_str1 (y, "2.991959870867646566478e-231"))
344 {
345 printf ("Error for x=-1683977482443233/2^41\n");
346 exit (1);
347 }
348
349 mpfr_set_prec (x, 10);
350 mpfr_set_prec (y, 10);
351 /* save emin */
352 emin = mpfr_get_emin ();
353 set_emin (-10);
354 mpfr_set_si (x, -12, MPFR_RNDN);
355 mpfr_exp2 (y, x, MPFR_RNDN);
356 if (MPFR_NOTZERO (y) || MPFR_IS_NEG (y))
357 {
358 printf ("Error for x=emin-2, RNDN\n");
359 printf ("Expected +0\n");
360 printf ("Got "); mpfr_dump (y);
361 exit (1);
362 }
363 /* restore emin */
364 set_emin (emin);
365
366 /* save emax */
367 emax = mpfr_get_emax ();
368 set_emax (10);
369 mpfr_set_ui (x, 11, MPFR_RNDN);
370 mpfr_exp2 (y, x, MPFR_RNDN);
371 if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0)
372 {
373 printf ("Error for x=emax+1, RNDN\n");
374 exit (1);
375 }
376 /* restore emax */
377 set_emax (emax);
378
379 MPFR_SET_INF(x);
380 MPFR_SET_POS(x);
381 mpfr_exp2 (y, x, MPFR_RNDN);
382 if(!MPFR_IS_INF(y))
383 {
384 printf ("evaluation of function in INF does not return INF\n");
385 exit (1);
386 }
387
388 MPFR_CHANGE_SIGN(x);
389 mpfr_exp2 (y, x, MPFR_RNDN);
390 if(!MPFR_IS_ZERO(y))
391 {
392 printf ("evaluation of function in -INF does not return 0\n");
393 exit (1);
394 }
395
396 MPFR_SET_NAN(x);
397 mpfr_exp2 (y, x, MPFR_RNDN);
398 if(!MPFR_IS_NAN(y))
399 {
400 printf ("evaluation of function in NaN does not return NaN\n");
401 exit (1);
402 }
403
404 if ((mpfr_uexp_t) 8 << 31 != 0 ||
405 mpfr_get_emax () <= (mpfr_uexp_t) 100000 * 100000)
406 {
407 /* emax <= 10000000000 */
408 mpfr_set_prec (x, 40);
409 mpfr_set_prec (y, 40);
410 mpfr_set_str (x, "10000000000.5", 10, MPFR_RNDN);
411 mpfr_clear_flags ();
412 mpfr_exp2 (y, x, MPFR_RNDN);
413 if (!(MPFR_IS_INF (y) && MPFR_IS_POS (y) && mpfr_overflow_p ()))
414 {
415 printf ("exp2(10000000000.5) should overflow.\n");
416 exit (1);
417 }
418 }
419
420 mpfr_set_prec (x, 2);
421 mpfr_set_prec (y, 2);
422 mpfr_set_str_binary (x, "-1.0E-26");
423 mpfr_exp2 (y, x, MPFR_RNDD);
424 mpfr_set_str_binary (x, "1.1E-1");
425 if (mpfr_cmp (x, y))
426 {
427 printf ("Error for exp(-2^(-26)) for prec=2\n");
428 exit (1);
429 }
430
431 test_generic (MPFR_PREC_MIN, 100, 100);
432
433 mpfr_clear (x);
434 mpfr_clear (y);
435
436 overflowed_exp2_0 ();
437
438 data_check ("data/exp2", mpfr_exp2, "mpfr_exp2");
439
440 tests_end_mpfr ();
441 return 0;
442 }
443