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