xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tadd1sp.c (revision ba125506a622fe649968631a56eba5d42ff57863)
1 /* Test file for mpfr_add1sp.
2 
3 Copyright 2004-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 static void check_random (mpfr_prec_t p);
27 
28 static int
mpfr_add_cf(mpfr_ptr a,mpfr_srcptr b,mpfr_srcptr c,mpfr_rnd_t r)29 mpfr_add_cf (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t r)
30 {
31   mpfr_clear_flags ();  /* allows better checking */
32   return mpfr_add (a, b, c, r);
33 }
34 
35 static void
check_overflow(void)36 check_overflow (void)
37 {
38   mpfr_t x, y, z1, z2;
39   mpfr_exp_t emin, emax;
40 
41   emin = mpfr_get_emin ();
42   emax = mpfr_get_emax ();
43 
44   set_emin (-1021);
45   set_emax (1024);
46 
47   mpfr_inits (x, y, z1, z2, (mpfr_ptr) 0);
48 
49   mpfr_set_str1 (x, "8.00468257869324898448e+307");
50   mpfr_set_str1 (y, "7.44784712422708645156e+307");
51   mpfr_add1sp (z1, x, y, MPFR_RNDN);
52   mpfr_add1   (z2, x, y, MPFR_RNDN);
53   if (mpfr_cmp (z1, z2))
54     {
55       printf ("Overflow bug in add1sp.\n");
56       exit (1);
57     }
58   mpfr_clears (x, y, z1, z2, (mpfr_ptr) 0);
59 
60   set_emin (emin);
61   set_emax (emax);
62 }
63 
64 static void
bug20171217(void)65 bug20171217 (void)
66 {
67   mpfr_t a, b, c;
68 
69   mpfr_init2 (a, 137);
70   mpfr_init2 (b, 137);
71   mpfr_init2 (c, 137);
72   mpfr_set_str_binary (b, "0.11111111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000E-66");
73   mpfr_set_str_binary (c, "0.11111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000110000E-2");
74   mpfr_add_cf (a, b, c, MPFR_RNDN);
75   mpfr_set_str_binary (b, "0.10000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000001000E-1");
76   MPFR_ASSERTN(mpfr_equal_p (a, b));
77   mpfr_clear (a);
78   mpfr_clear (b);
79   mpfr_clear (c);
80 }
81 
82 static void
bug20190903(void)83 bug20190903 (void)
84 {
85   mpfr_t a, b, c, d;
86   int inex;
87   mpfr_flags_t flags;
88 
89   /* Bug in r13574, fixed in r13578.
90      Note: to reproduce the failure, GMP_NUMB_BITS == 64 is assumed. */
91   mpfr_inits2 (128, a, b, c, d, (mpfr_ptr) 0);
92   mpfr_set_str_binary (b, "0.11111111111111111100000000000000000001001111111101111111110000101001111100111110110010011001111110000000101001001001110110101110E0");
93   mpfr_set_str_binary (c, "0.10000001011101000010000111100111011110100000001001000010011011001000110100111111101100001101001101011101100100011000000101110111E-126");
94   mpfr_add_cf (a, b, c, MPFR_RNDN);
95   mpfr_set_str_binary (b, "0.11111111111111111100000000000000000001001111111101111111110000101001111100111110110010011001111110000000101001001001110110110000E0");
96   MPFR_ASSERTN (mpfr_equal_p (a, b));
97   mpfr_clears (a, b, c, d, (mpfr_ptr) 0);
98 
99   /* Bug in r13574, fixed in r13586. */
100   /* Figure with GMP_NUMB_BITS = 4:
101        b = 1111 1000
102        c =      1000 0001
103   */
104   mpfr_inits2 (2 * GMP_NUMB_BITS, a, b, c, d, (mpfr_ptr) 0);
105   mpfr_set_ui_2exp (d, 1, 3 * GMP_NUMB_BITS, MPFR_RNDN);
106   mpfr_set_ui_2exp (c, 1, 2 * GMP_NUMB_BITS - 1, MPFR_RNDN);
107   mpfr_sub (b, d, c, MPFR_RNDN);
108   mpfr_add_ui (c, c, 1, MPFR_RNDN);
109   inex = mpfr_add_cf (a, b, c, MPFR_RNDN);
110   flags = __gmpfr_flags;
111   MPFR_ASSERTN (mpfr_equal_p (a, d));
112   MPFR_ASSERTN (inex < 0);
113   MPFR_ASSERTN (flags == MPFR_FLAGS_INEXACT);
114   inex = mpfr_add_cf (a, b, c, MPFR_RNDU);
115   flags = __gmpfr_flags;
116   mpfr_add_ui (d, d, 1, MPFR_RNDU);
117   MPFR_ASSERTN (mpfr_equal_p (a, d));
118   MPFR_ASSERTN (inex > 0);
119   MPFR_ASSERTN (flags == MPFR_FLAGS_INEXACT);
120   mpfr_clears (a, b, c, d, (mpfr_ptr) 0);
121 }
122 
123 /* Check corner case b = 1, c = 2^(-p) for MPFR_PREC_MIN <= p <= pmax.
124    With RNDN, result is 1, except for p=1, where it is 2. */
125 static void
test_corner_1(mpfr_prec_t pmax)126 test_corner_1 (mpfr_prec_t pmax)
127 {
128   mpfr_prec_t p;
129 
130   for (p = MPFR_PREC_MIN; p <= pmax; p++)
131     {
132       mpfr_t a, b, c;
133       int inex;
134       mpfr_init2 (a, p);
135       mpfr_init2 (b, p);
136       mpfr_init2 (c, p);
137       mpfr_set_ui (b, 1, MPFR_RNDN);
138       mpfr_set_ui_2exp (c, 1, -p, MPFR_RNDN);
139       inex = mpfr_add_cf (a, b, c, MPFR_RNDN);
140       if (p == 1) /* special case, since 2^(p-1) is odd */
141         {
142           MPFR_ASSERTN(inex > 0);
143           MPFR_ASSERTN(mpfr_cmp_ui (a, 2) == 0);
144         }
145       else
146         {
147           MPFR_ASSERTN(inex < 0);
148           MPFR_ASSERTN(mpfr_cmp_ui (a, 1) == 0);
149         }
150       mpfr_clear (a);
151       mpfr_clear (b);
152       mpfr_clear (c);
153     }
154 }
155 
156 static void
coverage(void)157 coverage (void)
158 {
159   mpfr_t a, b, c;
160   int inex;
161   mpfr_exp_t emax;
162   mpfr_prec_t p;
163 
164   mpfr_init (a);
165   mpfr_init (b);
166   mpfr_init (c);
167 
168   /* coverage test in mpfr_add1sp: case round away, where add_one_ulp
169      gives a carry, and the new exponent is below emax */
170   for (p = MPFR_PREC_MIN; p <= 3 * GMP_NUMB_BITS; p++)
171     {
172       mpfr_set_prec (a, p);
173       mpfr_set_prec (b, p);
174       mpfr_set_prec (c, p);
175       mpfr_set_ui (b, 1, MPFR_RNDN);
176       mpfr_nextbelow (b); /* b = 1 - 2^(-p) (including for p=1) */
177       mpfr_set_ui_2exp (c, 1, -p-1, MPFR_RNDN);
178       /* c = 2^(-p-1) thus b+c = 1 - 2^(-p-1) should be rounded to 1 */
179       inex = mpfr_add_cf (a, b, c, MPFR_RNDU);
180       MPFR_ASSERTN(inex > 0);
181       MPFR_ASSERTN(mpfr_cmp_ui (a, 1) == 0);
182     }
183 
184   /* coverage test in mpfr_add1sp2: case GMP_NUMB_BITS <= d < 2*GMP_NUMB_BITS
185      and a1 = 0 */
186   mpfr_set_prec (a, GMP_NUMB_BITS + 2);
187   mpfr_set_prec (b, GMP_NUMB_BITS + 2);
188   mpfr_set_prec (c, GMP_NUMB_BITS + 2);
189   mpfr_set_ui (b, 1, MPFR_RNDN);
190   mpfr_nextbelow (b); /* b = 1 - 2^(-p) with p = GMP_NUMB_BITS+2 */
191   mpfr_set_ui_2exp (c, 1, -GMP_NUMB_BITS-1, MPFR_RNDN);
192   mpfr_nextbelow (c); /* c = 2^(1-p) - 2^(1-2p) */
193   /* a = 1 + 2^(-p) - 2^(1-2p) should be rounded to 1 with RNDN */
194   inex = mpfr_add_cf (a, b, c, MPFR_RNDN);
195   MPFR_ASSERTN(inex < 0);
196   MPFR_ASSERTN(mpfr_cmp_ui (a, 1) == 0);
197 
198   /* coverage test in mpfr_add1sp2: case round away, where add_one_ulp
199      gives a carry, and the new exponent is below emax */
200   mpfr_set_prec (a, GMP_NUMB_BITS + 1);
201   mpfr_set_prec (b, GMP_NUMB_BITS + 1);
202   mpfr_set_prec (c, GMP_NUMB_BITS + 1);
203   mpfr_set_ui (b, 1, MPFR_RNDN);
204   mpfr_nextbelow (b); /* b = 1 - 2^(-p) */
205   mpfr_set_ui_2exp (c, 1, -GMP_NUMB_BITS-2, MPFR_RNDN);
206   /* c = 2^(-p-1) */
207   inex = mpfr_add_cf (a, b, c, MPFR_RNDU);
208   MPFR_ASSERTN(inex > 0);
209   MPFR_ASSERTN(mpfr_cmp_ui (a, 1) == 0);
210 
211   /* coverage test in mpfr_add1sp3: case GMP_NUMB_BITS <= d < 2*GMP_NUMB_BITS
212      and a2 == 0 */
213   mpfr_set_prec (a, 2 * GMP_NUMB_BITS + 2);
214   mpfr_set_prec (b, 2 * GMP_NUMB_BITS + 2);
215   mpfr_set_prec (c, 2 * GMP_NUMB_BITS + 2);
216   mpfr_set_ui (b, 1, MPFR_RNDN);
217   mpfr_nextbelow (b); /* b = 1 - 2^(-p) with p = 2*GMP_NUMB_BITS+2 */
218   mpfr_set_ui_2exp (c, 1, -2*GMP_NUMB_BITS-1, MPFR_RNDN);
219   mpfr_nextbelow (c); /* c = 2^(1-p) - 2^(1-2p) */
220   /* a = 1 + 2^(-p) - 2^(1-2p) should be rounded to 1 with RNDN */
221   inex = mpfr_add_cf (a, b, c, MPFR_RNDN);
222   MPFR_ASSERTN(inex < 0);
223   MPFR_ASSERTN(mpfr_cmp_ui (a, 1) == 0);
224 
225   /* coverage test in mpfr_add1sp3: case bx > emax */
226   emax = mpfr_get_emax ();
227   set_emax (1);
228   mpfr_set_prec (a, 2 * GMP_NUMB_BITS + 1);
229   mpfr_set_prec (b, 2 * GMP_NUMB_BITS + 1);
230   mpfr_set_prec (c, 2 * GMP_NUMB_BITS + 1);
231   mpfr_set_ui_2exp (b, 1, mpfr_get_emax () - 1, MPFR_RNDN);
232   mpfr_nextbelow (b);
233   mpfr_mul_2ui (b, b, 1, MPFR_RNDN);
234   /* now b is the largest number < +Inf */
235   mpfr_div_2ui (c, b, GMP_NUMB_BITS - 1, MPFR_RNDN);
236   /* we are in the case d < GMP_NUMB_BITS of mpfr_add1sp3 */
237   inex = mpfr_add_cf (a, b, b, MPFR_RNDU);
238   MPFR_ASSERTN(inex > 0);
239   MPFR_ASSERTN(mpfr_inf_p (a) && mpfr_sgn (a) > 0);
240   set_emax (emax);
241 
242   /* coverage test in mpfr_add1sp3: case round away, where add_one_ulp gives
243      a carry, no overflow */
244   mpfr_set_prec (a, 2 * GMP_NUMB_BITS + 1);
245   mpfr_set_prec (b, 2 * GMP_NUMB_BITS + 1);
246   mpfr_set_prec (c, 2 * GMP_NUMB_BITS + 1);
247   mpfr_set_ui (b, 1, MPFR_RNDN);
248   mpfr_nextbelow (b); /* b = 1 - 2^(-p) */
249   mpfr_set_ui_2exp (c, 1, -2 * GMP_NUMB_BITS - 2, MPFR_RNDN);
250   /* c = 2^(-p-1) */
251   inex = mpfr_add_cf (a, b, c, MPFR_RNDU);
252   MPFR_ASSERTN(inex > 0);
253   MPFR_ASSERTN(mpfr_cmp_ui (a, 1) == 0);
254 
255   /* coverage test in mpfr_add1sp3: case round away, where add_one_ulp gives
256      a carry, with overflow */
257   emax = mpfr_get_emax ();
258   set_emax (1);
259   mpfr_set_prec (a, 2 * GMP_NUMB_BITS + 1);
260   mpfr_set_prec (b, 2 * GMP_NUMB_BITS + 1);
261   mpfr_set_prec (c, 2 * GMP_NUMB_BITS + 1);
262   mpfr_set_ui_2exp (b, 1, mpfr_get_emax () - 1, MPFR_RNDN);
263   mpfr_nextbelow (b);
264   mpfr_mul_2ui (b, b, 1, MPFR_RNDN);
265   /* now b is the largest number < +Inf */
266   mpfr_set_ui_2exp (c, 1, mpfr_get_emin () - 1, MPFR_RNDN);
267   inex = mpfr_add_cf (a, b, c, MPFR_RNDU);
268   MPFR_ASSERTN(inex > 0);
269   MPFR_ASSERTN(mpfr_inf_p (a) && mpfr_sgn (a) > 0);
270   set_emax (emax);
271 
272   mpfr_clear (a);
273   mpfr_clear (b);
274   mpfr_clear (c);
275 }
276 
277 int
main(void)278 main (void)
279 {
280   mpfr_prec_t p;
281   int i;
282 
283   tests_start_mpfr ();
284 
285   coverage ();
286   test_corner_1 (1024);
287   bug20171217 ();
288   bug20190903 ();
289   check_special ();
290   for (p = MPFR_PREC_MIN; p < 200; p++)
291     check_random (p);
292   for (i = 0; i < 200; i++)
293     {
294       /* special precisions */
295       check_random (GMP_NUMB_BITS);
296       check_random (2 * GMP_NUMB_BITS);
297     }
298   check_overflow ();
299 
300   tests_end_mpfr ();
301   return 0;
302 }
303 
304 #define STD_ERROR                                                       \
305   do                                                                    \
306     {                                                                   \
307       printf("ERROR: for %s and p=%lu and i=%d:\nB=",                   \
308              mpfr_print_rnd_mode ((mpfr_rnd_t) r), (unsigned long) p, i); \
309       mpfr_dump (b);                                                    \
310       printf ("C="); mpfr_dump (c);                                     \
311       printf ("add1  : "); mpfr_dump (a1);                              \
312       printf ("add1sp: "); mpfr_dump (a2);                              \
313       exit(1);                                                          \
314     }                                                                   \
315   while (0)
316 
317 #define STD_ERROR2                                                      \
318   do                                                                    \
319     {                                                                   \
320       printf("ERROR: Wrong inexact flag for %s and p=%lu and i=%d:\nB=", \
321              mpfr_print_rnd_mode ((mpfr_rnd_t) r), (unsigned long) p, i); \
322       mpfr_dump (b);                                                    \
323       printf ("C="); mpfr_dump (c);                                     \
324       printf ("A="); mpfr_dump (a1);                                    \
325       printf ("Add1: %d. Add1sp: %d\n", inexact1, inexact2);            \
326       exit(1);                                                          \
327     }                                                                   \
328  while (0)
329 
330 #define SET_PREC(_p)                                    \
331   do                                                    \
332     {                                                   \
333       p = _p;                                           \
334       mpfr_set_prec(a1, _p); mpfr_set_prec(a2, _p);     \
335       mpfr_set_prec(b,  _p); mpfr_set_prec(c,  _p);     \
336     }                                                   \
337   while (0)
338 
339 static void
check_random(mpfr_prec_t p)340 check_random (mpfr_prec_t p)
341 {
342   mpfr_t a1, a2, b, bs, c, cs;
343   int r;
344   int i, inexact1, inexact2;
345 
346   mpfr_inits2 (p, a1, a2, b, c, (mpfr_ptr) 0);
347 
348   for (i = 0 ; i < 500 ; i++)
349     {
350       mpfr_urandom (b, RANDS, MPFR_RNDA);
351       mpfr_urandom (c, RANDS, MPFR_RNDA);
352       if (MPFR_IS_PURE_FP(b) && MPFR_IS_PURE_FP(c))
353         {
354           if (RAND_BOOL ())
355             mpfr_neg (b, b, MPFR_RNDN);
356           if (RAND_BOOL ())
357             mpfr_neg (c, c, MPFR_RNDN);
358           if (MPFR_GET_EXP(b) < MPFR_GET_EXP(c))
359             {
360               /* Exchange b and c, except the signs (actually, the sign
361                  of cs doesn't matter). */
362               MPFR_ALIAS (bs, c, MPFR_SIGN (b), MPFR_EXP (c));
363               MPFR_ALIAS (cs, b, MPFR_SIGN (c), MPFR_EXP (b));
364             }
365           else
366             {
367               MPFR_ALIAS (bs, b, MPFR_SIGN (b), MPFR_EXP (b));
368               MPFR_ALIAS (cs, c, MPFR_SIGN (c), MPFR_EXP (c));
369             }
370           RND_LOOP (r)
371             {
372               mpfr_flags_t flags1, flags2;
373 
374               if (r == MPFR_RNDF) /* inexact makes no sense, moreover
375                                      mpfr_add1 and mpfr_add1sp could
376                                      return different values */
377                 continue;
378 
379               mpfr_clear_flags ();
380               inexact1 = mpfr_add1 (a1, bs, cs, (mpfr_rnd_t) r);
381               flags1 = __gmpfr_flags;
382               mpfr_clear_flags ();
383               inexact2 = mpfr_add1sp (a2, b, c, (mpfr_rnd_t) r);
384               flags2 = __gmpfr_flags;
385               if (! mpfr_equal_p (a1, a2))
386                 STD_ERROR;
387               if (inexact1 != inexact2)
388                 STD_ERROR2;
389               MPFR_ASSERTN (flags1 == flags2);
390             }
391         }
392     }
393 
394   mpfr_clears (a1, a2, b, c, (mpfr_ptr) 0);
395 }
396 
397 static void
check_special(void)398 check_special (void)
399 {
400   mpfr_t a1, a2, b, c;
401   int r;
402   mpfr_prec_t p;
403   int i = -1, inexact1, inexact2;
404 
405   mpfr_inits (a1, a2, b, c, (mpfr_ptr) 0);
406 
407   RND_LOOP (r)
408     {
409       if (r == MPFR_RNDF)
410         continue; /* inexact makes no sense, mpfr_add1 and mpfr_add1sp
411                      could differ */
412       SET_PREC(53);
413       mpfr_set_str1 (b, "1@100");
414       mpfr_set_str1 (c, "1@1");
415       inexact1 = mpfr_add1(a1, b, c, (mpfr_rnd_t) r);
416       inexact2 = mpfr_add1sp(a2, b, c, (mpfr_rnd_t) r);
417       if (mpfr_cmp(a1, a2))
418         STD_ERROR;
419       if (inexact1 != inexact2)
420         STD_ERROR2;
421       mpfr_set_str_binary (b, "1E53");
422       mpfr_set_str_binary (c, "1E0");
423       inexact1 = mpfr_add1(a1, b, c, (mpfr_rnd_t) r);
424       inexact2 = mpfr_add1sp(a2, b, c, (mpfr_rnd_t) r);
425       if (mpfr_cmp(a1, a2))
426         STD_ERROR;
427       if (inexact1 != inexact2)
428         STD_ERROR2;
429     }
430 
431   mpfr_set_prec (c, 2);
432   mpfr_set_prec (a1, 2);
433   mpfr_set_prec (a2, 2);
434   mpfr_set_str_binary (c, "1.0e1");
435   mpfr_set_str_binary (a2, "1.1e-1");
436   mpfr_set_str_binary (a1, "0.11E2");
437   mpfr_add1sp (a2, c, a2, MPFR_RNDN);
438   if (mpfr_cmp (a1, a2))
439     {
440       printf ("Regression reuse test failed!\n");
441       exit (1);
442     }
443 
444   mpfr_set_prec (a1, 63);
445   mpfr_set_prec (b, 63);
446   mpfr_set_prec (c, 63);
447   mpfr_set_str_binary (b, "0.111111101010110111010100110101010110000101111011011011100011001E-3");
448   mpfr_set_str_binary (c, "0.101111111101110000001100001000011000011011010001010011111100111E-4");
449   mpfr_clear_inexflag ();
450   mpfr_add1sp (a1, b, c, MPFR_RNDN);
451   MPFR_ASSERTN (mpfr_inexflag_p ());
452 
453   mpfr_clears (a1, a2, b, c, (mpfr_ptr) 0);
454 }
455