xref: /netbsd/external/lgpl3/mpfr/dist/tests/texp2.c (revision 606004a0)
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