1 /* Test file for features related to exceptions.
2
3 Copyright 2001-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 PRINT_ERROR(s) do { printf ("%s\n", s); exit (1); } while (0)
26
27 /* Test powerof2 */
28 static void
check_powerof2(void)29 check_powerof2 (void)
30 {
31 mpfr_t x;
32
33 mpfr_init (x);
34 mpfr_set_ui (x, 1, MPFR_RNDN);
35 MPFR_ASSERTN (mpfr_powerof2_raw (x));
36 mpfr_set_ui (x, 3, MPFR_RNDN);
37 MPFR_ASSERTN (!mpfr_powerof2_raw (x));
38 mpfr_clear (x);
39 }
40
41 /* Test default rounding mode */
42 static void
check_default_rnd(void)43 check_default_rnd (void)
44 {
45 int r;
46 mpfr_rnd_t t;
47 RND_LOOP (r)
48 {
49 mpfr_set_default_rounding_mode ((mpfr_rnd_t) r);
50 t = (mpfr_get_default_rounding_mode) ();
51 if ((mpfr_rnd_t) r != t)
52 {
53 printf ("%s %s\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r),
54 mpfr_print_rnd_mode (t));
55 PRINT_ERROR ("ERROR in setting / getting default rounding mode (1)");
56 }
57 }
58 mpfr_set_default_rounding_mode ((mpfr_rnd_t) MPFR_RND_MAX);
59 if (mpfr_get_default_rounding_mode() != MPFR_RNDF)
60 PRINT_ERROR ("ERROR in setting / getting default rounding mode (2)");
61 mpfr_set_default_rounding_mode((mpfr_rnd_t) -1);
62 if (mpfr_get_default_rounding_mode() != MPFR_RNDF)
63 PRINT_ERROR ("ERROR in setting / getting default rounding mode (3)");
64 }
65
66 static void
check_emin_emax(void)67 check_emin_emax (void)
68 {
69 mpfr_exp_t old_emin, old_emax;
70
71 old_emin = mpfr_get_emin ();
72 old_emax = mpfr_get_emax ();
73
74 /* Check the functions not the macros ! */
75 if ((mpfr_set_emin)(MPFR_EMIN_MIN) != 0)
76 PRINT_ERROR ("set_emin failed!");
77 if ((mpfr_get_emin)() != MPFR_EMIN_MIN)
78 PRINT_ERROR ("get_emin FAILED!");
79 if ((mpfr_set_emin)(MPFR_EMIN_MIN-1) == 0)
80 PRINT_ERROR ("set_emin failed! (2)");
81
82 if ((mpfr_set_emax)(MPFR_EMAX_MAX) != 0)
83 PRINT_ERROR ("set_emax failed!");
84 if ((mpfr_get_emax)() != MPFR_EMAX_MAX)
85 PRINT_ERROR ("get_emax FAILED!");
86 if ((mpfr_set_emax)(MPFR_EMAX_MAX+1) == 0)
87 PRINT_ERROR ("set_emax failed! (2)");
88
89 if ((mpfr_get_emin_min) () != MPFR_EMIN_MIN)
90 PRINT_ERROR ("get_emin_min");
91 if ((mpfr_get_emin_max) () != MPFR_EMIN_MAX)
92 PRINT_ERROR ("get_emin_max");
93 if ((mpfr_get_emax_min) () != MPFR_EMAX_MIN)
94 PRINT_ERROR ("get_emax_min");
95 if ((mpfr_get_emax_max) () != MPFR_EMAX_MAX)
96 PRINT_ERROR ("get_emax_max");
97
98 set_emin (old_emin);
99 set_emax (old_emax);
100 }
101
102 static void
check_get_prec(void)103 check_get_prec (void)
104 {
105 mpfr_t x;
106 int i = 0;
107
108 mpfr_init2 (x, 17);
109
110 if (mpfr_get_prec (x) != 17 || (mpfr_get_prec) (x) != 17)
111 PRINT_ERROR ("mpfr_get_prec");
112
113 #ifdef IGNORE_CPP_COMPAT
114 #pragma GCC diagnostic push
115 #pragma GCC diagnostic ignored "-Wc++-compat"
116 #endif
117
118 if (mpfr_get_prec ((i++, VOIDP_CAST(x))) != 17)
119 PRINT_ERROR ("mpfr_get_prec (2)");
120
121 #ifdef IGNORE_CPP_COMPAT
122 #pragma GCC diagnostic pop
123 #endif
124
125 MPFR_ASSERTN (i == 1);
126 mpfr_clear (x);
127 }
128
129 static void
mpfr_set_double_range(void)130 mpfr_set_double_range (void)
131 {
132 mpfr_set_default_prec (54);
133 if (mpfr_get_default_prec () != 54)
134 PRINT_ERROR ("get_default_prec failed (1)");
135 mpfr_set_default_prec (53);
136 if ((mpfr_get_default_prec) () != 53)
137 PRINT_ERROR ("get_default_prec failed (2)");
138
139 /* in double precision format, the unbiased exponent is between 0 and
140 2047, where 0 is used for subnormal numbers, and 2047 for special
141 numbers (infinities, NaN), and the bias is 1023, thus "normal" numbers
142 have an exponent between -1022 and 1023, corresponding to numbers
143 between 2^(-1022) and previous(2^(1024)).
144 (The smallest subnormal number is 0.(0^51)1*2^(-1022)= 2^(-1074).)
145
146 The smallest normal power of two is 1.0*2^(-1022).
147 The largest normal power of two is 2^1023.
148 (We have to add one for mpfr since mantissa are between 1/2 and 1.)
149 */
150
151 set_emin (-1021);
152 set_emax (1024);
153 }
154
155 static void
check_flags(void)156 check_flags (void)
157 {
158 mpfr_t x;
159 mpfr_exp_t old_emin, old_emax;
160
161 old_emin = mpfr_get_emin ();
162 old_emax = mpfr_get_emax ();
163 mpfr_init (x);
164
165 /* Check the functions not the macros ! */
166 (mpfr_clear_flags)();
167 mpfr_set_double_range ();
168
169 mpfr_set_ui (x, 1, MPFR_RNDN);
170 (mpfr_clear_overflow)();
171 mpfr_mul_2ui (x, x, 1024, MPFR_RNDN);
172 if (!(mpfr_overflow_p)())
173 PRINT_ERROR ("ERROR: No overflow detected!\n");
174
175 (mpfr_clear_underflow)();
176 mpfr_set_ui (x, 1, MPFR_RNDN);
177 mpfr_div_2ui (x, x, 1025, MPFR_RNDN);
178 if (!(mpfr_underflow_p)())
179 PRINT_ERROR ("ERROR: No underflow detected!\n");
180
181 (mpfr_clear_nanflag)();
182 MPFR_SET_NAN(x);
183 mpfr_add (x, x, x, MPFR_RNDN);
184 if (!(mpfr_nanflag_p)())
185 PRINT_ERROR ("ERROR: No NaN flag!\n");
186
187 (mpfr_clear_inexflag)();
188 mpfr_set_ui(x, 2, MPFR_RNDN);
189 mpfr_cos(x, x, MPFR_RNDN);
190 if (!(mpfr_inexflag_p)())
191 PRINT_ERROR ("ERROR: No inexact flag!\n");
192
193 (mpfr_clear_erangeflag) ();
194 mpfr_set_ui (x, 1, MPFR_RNDN);
195 mpfr_mul_2ui (x, x, 1024, MPFR_RNDN);
196 mpfr_get_ui (x, MPFR_RNDN);
197 if (!(mpfr_erangeflag_p)())
198 PRINT_ERROR ("ERROR: No erange flag!\n");
199
200 mpfr_clear (x);
201 set_emin (old_emin);
202 set_emax (old_emax);
203 }
204
205 static void
test_set_underflow(void)206 test_set_underflow (void)
207 {
208 mpfr_t x, zero, min;
209 mpfr_ptr r[MPFR_RND_MAX];
210 int t[MPFR_RND_MAX] = { 1, -1, 1, -1, 1 }; /* RNDN, RNDZ, RNDU, RNDD, RNDA */
211 int i;
212 int s;
213
214 mpfr_inits (x, zero, min, (mpfr_ptr) 0);
215 mpfr_set_ui (zero, 0, MPFR_RNDN);
216 mpfr_set_ui (min, 0, MPFR_RNDN);
217 mpfr_nextabove (min);
218 r[0] = r[2] = r[4] = min; /* RNDN, RNDU, RNDA */
219 r[1] = r[3] = zero; /* RNDZ, RNDD */
220 for (s = 1; s > 0; s = -1)
221 {
222 RND_LOOP (i)
223 {
224 int j;
225 int inex;
226
227 j = s < 0 && i > 1 ? 5 - i : i;
228 inex = mpfr_underflow (x, (mpfr_rnd_t) i, s);
229 /* for RNDF, inex has no meaning, just check that x is either
230 min or zero */
231 if (i == MPFR_RNDF)
232 {
233 if (mpfr_cmp (x, min) && mpfr_cmp (x, zero))
234 {
235 printf ("Error in test_set_underflow, sign = %d,"
236 " rnd_mode = %s\n", s, mpfr_print_rnd_mode ((mpfr_rnd_t) i));
237 printf ("Got\n");
238 mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN);
239 printf ("\ninstead of\n");
240 mpfr_out_str (stdout, 2, 0, zero, MPFR_RNDN);
241 printf ("\nor\n");
242 mpfr_out_str (stdout, 2, 0, min, MPFR_RNDN);
243 printf ("\n");
244 exit (1);
245 }
246 }
247 else if (mpfr_cmp (x, r[j]) || inex * t[j] <= 0)
248 {
249 printf ("Error in test_set_underflow, sign = %d,"
250 " rnd_mode = %s\n", s, mpfr_print_rnd_mode ((mpfr_rnd_t) i));
251 printf ("Got\n");
252 mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN);
253 printf (", inex = %d\ninstead of\n", inex);
254 mpfr_out_str (stdout, 2, 0, r[j], MPFR_RNDN);
255 printf (", inex = %d\n", t[j]);
256 exit (1);
257 }
258 }
259 mpfr_neg (zero, zero, MPFR_RNDN);
260 mpfr_neg (min, min, MPFR_RNDN);
261 }
262 mpfr_clears (x, zero, min, (mpfr_ptr) 0);
263 }
264
265 static void
test_set_overflow(void)266 test_set_overflow (void)
267 {
268 mpfr_t x, inf, max;
269 mpfr_ptr r[MPFR_RND_MAX];
270 int t[MPFR_RND_MAX] = { 1, -1, 1, -1, 1 }; /* RNDN, RNDZ, RNDU, RNDD, RNDA */
271 int i;
272 int s;
273
274 mpfr_inits2 (32, x, inf, max, (mpfr_ptr) 0);
275 mpfr_set_inf (inf, 1);
276 mpfr_set_inf (max, 1);
277 mpfr_nextbelow (max);
278 r[0] = r[2] = r[4] = inf; /* RNDN, RNDU, RNDA */
279 r[1] = r[3] = max; /* RNDZ, RNDD */
280 for (s = 1; s > 0; s = -1)
281 {
282 RND_LOOP (i)
283 {
284 int j;
285 int inex;
286
287 j = s < 0 && i > 1 ? 5 - i : i;
288 inex = mpfr_overflow (x, (mpfr_rnd_t) i, s);
289 /* for RNDF, inex has no meaning, just check that x is either
290 max or inf */
291 if (i == MPFR_RNDF)
292 {
293 if (mpfr_cmp (x, max) && mpfr_cmp (x, inf))
294 {
295 printf ("Error in test_set_overflow, sign = %d,"
296 " rnd_mode = %s\n", s, mpfr_print_rnd_mode ((mpfr_rnd_t) i));
297 printf ("Got\n");
298 mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN);
299 printf ("\ninstead of\n");
300 mpfr_out_str (stdout, 2, 0, max, MPFR_RNDN);
301 printf ("\nor\n");
302 mpfr_out_str (stdout, 2, 0, inf, MPFR_RNDN);
303 printf ("\n");
304 exit (1);
305 }
306 }
307 else if (mpfr_cmp (x, r[j]) || inex * t[j] <= 0)
308 {
309 printf ("Error in test_set_overflow, sign = %d,"
310 " rnd_mode = %s\n", s, mpfr_print_rnd_mode ((mpfr_rnd_t) i));
311 printf ("Got\n");
312 mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN);
313 printf (", inex = %d\ninstead of\n", inex);
314 mpfr_out_str (stdout, 2, 0, r[j], MPFR_RNDN);
315 printf (", inex = %d\n", t[j]);
316 exit (1);
317 }
318 }
319 mpfr_neg (inf, inf, MPFR_RNDN);
320 mpfr_neg (max, max, MPFR_RNDN);
321 }
322 mpfr_clears (x, inf, max, (mpfr_ptr) 0);
323 }
324
325 static void
check_set(void)326 check_set (void)
327 {
328 mpfr_clear_flags ();
329
330 mpfr_set_overflow ();
331 MPFR_ASSERTN ((mpfr_overflow_p) ());
332 mpfr_set_underflow ();
333 MPFR_ASSERTN ((mpfr_underflow_p) ());
334 mpfr_set_divby0 ();
335 MPFR_ASSERTN ((mpfr_divby0_p) ());
336 mpfr_set_nanflag ();
337 MPFR_ASSERTN ((mpfr_nanflag_p) ());
338 mpfr_set_inexflag ();
339 MPFR_ASSERTN ((mpfr_inexflag_p) ());
340 mpfr_set_erangeflag ();
341 MPFR_ASSERTN ((mpfr_erangeflag_p) ());
342
343 MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_ALL);
344
345 mpfr_clear_overflow ();
346 MPFR_ASSERTN (! (mpfr_overflow_p) ());
347 mpfr_clear_underflow ();
348 MPFR_ASSERTN (! (mpfr_underflow_p) ());
349 mpfr_clear_divby0 ();
350 MPFR_ASSERTN (! (mpfr_divby0_p) ());
351 mpfr_clear_nanflag ();
352 MPFR_ASSERTN (! (mpfr_nanflag_p) ());
353 mpfr_clear_inexflag ();
354 MPFR_ASSERTN (! (mpfr_inexflag_p) ());
355 mpfr_clear_erangeflag ();
356 MPFR_ASSERTN (! (mpfr_erangeflag_p) ());
357
358 MPFR_ASSERTN (__gmpfr_flags == 0);
359
360 (mpfr_set_overflow) ();
361 MPFR_ASSERTN (mpfr_overflow_p ());
362 (mpfr_set_underflow) ();
363 MPFR_ASSERTN (mpfr_underflow_p ());
364 (mpfr_set_divby0) ();
365 MPFR_ASSERTN (mpfr_divby0_p ());
366 (mpfr_set_nanflag) ();
367 MPFR_ASSERTN (mpfr_nanflag_p ());
368 (mpfr_set_inexflag) ();
369 MPFR_ASSERTN (mpfr_inexflag_p ());
370 (mpfr_set_erangeflag) ();
371 MPFR_ASSERTN (mpfr_erangeflag_p ());
372
373 MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_ALL);
374
375 (mpfr_clear_overflow) ();
376 MPFR_ASSERTN (! mpfr_overflow_p ());
377 (mpfr_clear_underflow) ();
378 MPFR_ASSERTN (! mpfr_underflow_p ());
379 (mpfr_clear_divby0) ();
380 MPFR_ASSERTN (! mpfr_divby0_p ());
381 (mpfr_clear_nanflag) ();
382 MPFR_ASSERTN (! mpfr_nanflag_p ());
383 (mpfr_clear_inexflag) ();
384 MPFR_ASSERTN (! mpfr_inexflag_p ());
385 (mpfr_clear_erangeflag) ();
386 MPFR_ASSERTN (! mpfr_erangeflag_p ());
387
388 MPFR_ASSERTN (__gmpfr_flags == 0);
389 }
390
391 /* Note: this test assumes that mpfr_flags_* can be implemented as both
392 a function and a macro. Thus in such a case, both implementations are
393 tested. */
394 static void
check_groups(void)395 check_groups (void)
396 {
397 int i, j;
398 for (i = 0; i < 200; i++)
399 {
400 mpfr_flags_t f1, f2, mask;
401
402 f1 = __gmpfr_flags;
403 MPFR_ASSERTN (mpfr_flags_save () == f1);
404 MPFR_ASSERTN ((mpfr_flags_save) () == f1);
405 MPFR_ASSERTN (__gmpfr_flags == f1);
406 mask = randlimb () & MPFR_FLAGS_ALL;
407 if (RAND_BOOL ())
408 mpfr_flags_set (mask);
409 else
410 (mpfr_flags_set) (mask);
411 for (j = 1; j <= MPFR_FLAGS_ALL; j <<= 1)
412 if ((__gmpfr_flags & j) != ((mask & j) != 0 ? j : (f1 & j)))
413 {
414 printf ("mpfr_flags_set error: old = 0x%lx, group = 0x%lx, "
415 "new = 0x%lx, j = 0x%lx\n",
416 (unsigned long) f1, (unsigned long) mask,
417 (unsigned long) __gmpfr_flags, (unsigned long) j);
418 exit (1);
419 }
420
421 f2 = __gmpfr_flags;
422 mask = randlimb () & MPFR_FLAGS_ALL;
423 if (RAND_BOOL ())
424 mpfr_flags_clear (mask);
425 else
426 (mpfr_flags_clear) (mask);
427 for (j = 1; j <= MPFR_FLAGS_ALL; j <<= 1)
428 if ((__gmpfr_flags & j) != ((mask & j) != 0 ? 0 : (f2 & j)))
429 {
430 printf ("mpfr_flags_clear error: old = 0x%lx, group = 0x%lx, "
431 "new = 0x%lx, j = 0x%lx\n",
432 (unsigned long) f2, (unsigned long) mask,
433 (unsigned long) __gmpfr_flags, (unsigned long) j);
434 exit (1);
435 }
436
437 mask = randlimb () & MPFR_FLAGS_ALL;
438 f2 = RAND_BOOL () ? mpfr_flags_test (mask) : (mpfr_flags_test) (mask);
439 for (j = 1; j <= MPFR_FLAGS_ALL; j <<= 1)
440 if ((f2 & j) != ((mask & j) != 0 ? (__gmpfr_flags & j) : 0))
441 {
442 printf ("mpfr_flags_test error: current = 0x%lx, mask = 0x%lx, "
443 "res = 0x%lx, j = 0x%lx\n",
444 (unsigned long) __gmpfr_flags, (unsigned long) mask,
445 (unsigned long) f2, (unsigned long) j);
446 exit (1);
447 }
448
449 f2 = __gmpfr_flags;
450 if (RAND_BOOL ())
451 mpfr_flags_restore (f1, mask);
452 else
453 (mpfr_flags_restore) (f1, mask);
454 for (j = 1; j <= MPFR_FLAGS_ALL; j <<= 1)
455 if ((__gmpfr_flags & j) != (((mask & j) != 0 ? f1 : f2) & j))
456 {
457 printf ("mpfr_flags_restore error: old = 0x%lx, flags = 0x%lx, "
458 "mask = 0x%lx, new = 0x%lx, j = 0x%lx\n",
459 (unsigned long) f2, (unsigned long) f1,
460 (unsigned long) mask, (unsigned long) __gmpfr_flags,
461 (unsigned long) j);
462 exit (1);
463 }
464 }
465 }
466
467 int
main(int argc,char * argv[])468 main (int argc, char *argv[])
469 {
470 mpfr_t x, y;
471 mpfr_exp_t emin, emax;
472
473 tests_start_mpfr ();
474
475 test_set_underflow ();
476 test_set_overflow ();
477 check_default_rnd();
478
479 mpfr_init (x);
480 mpfr_init (y);
481
482 emin = mpfr_get_emin ();
483 emax = mpfr_get_emax ();
484 if (emin >= emax)
485 {
486 printf ("Error: emin >= emax\n");
487 exit (1);
488 }
489
490 mpfr_set_ui (x, 1, MPFR_RNDN);
491 mpfr_mul_2ui (x, x, 1024, MPFR_RNDN);
492 mpfr_set_double_range ();
493 mpfr_check_range (x, 0, MPFR_RNDN);
494 if (!mpfr_inf_p (x) || (mpfr_sgn(x) <= 0))
495 {
496 printf ("Error: 2^1024 rounded to nearest should give +Inf\n");
497 exit (1);
498 }
499
500 set_emax (1025);
501 mpfr_set_ui (x, 1, MPFR_RNDN);
502 mpfr_mul_2ui (x, x, 1024, MPFR_RNDN);
503 mpfr_set_double_range ();
504 mpfr_check_range (x, 0, MPFR_RNDD);
505 if (!mpfr_number_p (x))
506 {
507 printf ("Error: 2^1024 rounded down should give a normal number\n");
508 exit (1);
509 }
510
511 mpfr_set_ui (x, 1, MPFR_RNDN);
512 mpfr_mul_2ui (x, x, 1023, MPFR_RNDN);
513 mpfr_add (x, x, x, MPFR_RNDN);
514 if (!mpfr_inf_p (x) || (mpfr_sgn(x) <= 0))
515 {
516 printf ("Error: x+x rounded to nearest for x=2^1023 should give +Inf\n");
517 printf ("emax = %ld\n", (long) mpfr_get_emax ());
518 printf ("got "); mpfr_dump (x);
519 exit (1);
520 }
521
522 mpfr_set_ui (x, 1, MPFR_RNDN);
523 mpfr_mul_2ui (x, x, 1023, MPFR_RNDN);
524 mpfr_add (x, x, x, MPFR_RNDD);
525 if (!mpfr_number_p (x))
526 {
527 printf ("Error: x+x rounded down for x=2^1023 should give"
528 " a normal number\n");
529 exit (1);
530 }
531
532 mpfr_set_ui (x, 1, MPFR_RNDN);
533 mpfr_div_2ui (x, x, 1022, MPFR_RNDN);
534 mpfr_set_str_binary (y, "1.1e-1022"); /* y = 3/2*x */
535 mpfr_sub (y, y, x, MPFR_RNDZ);
536 if (mpfr_cmp_ui (y, 0))
537 {
538 printf ("Error: y-x rounded to zero should give 0"
539 " for y=3/2*2^(-1022), x=2^(-1022)\n");
540 printf ("Got "); mpfr_dump (y);
541 exit (1);
542 }
543
544 set_emin (-1026);
545 mpfr_set_ui (x, 1, MPFR_RNDN);
546 mpfr_div_2ui (x, x, 1025, MPFR_RNDN);
547 mpfr_set_double_range ();
548 mpfr_check_range (x, 0, MPFR_RNDN);
549 if (!MPFR_IS_ZERO (x) )
550 {
551 printf ("Error: x rounded to nearest for x=2^-1024 should give Zero\n");
552 printf ("emin = %ld\n", (long) mpfr_get_emin ());
553 printf ("got "); mpfr_dump (x);
554 exit (1);
555 }
556
557 mpfr_clear (x);
558 mpfr_clear (y);
559
560 set_emin (emin);
561 set_emax (emax);
562
563 check_emin_emax();
564 check_flags();
565 check_get_prec ();
566 check_powerof2 ();
567 check_set ();
568 check_groups ();
569
570 tests_end_mpfr ();
571 return 0;
572 }
573