xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tfmma.c (revision ba125506a622fe649968631a56eba5d42ff57863)
1 /* Test file for mpfr_fmma and mpfr_fmms.
2 
3 Copyright 2016-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 /* check both mpfr_fmma and mpfr_fmms */
26 static void
random_test(mpfr_ptr a,mpfr_ptr b,mpfr_ptr c,mpfr_ptr d,mpfr_rnd_t rnd)27 random_test (mpfr_ptr a, mpfr_ptr b, mpfr_ptr c, mpfr_ptr d, mpfr_rnd_t rnd)
28 {
29   mpfr_t ref, res, ab, cd;
30   int inex_ref, inex_res;
31   mpfr_prec_t p = MPFR_PREC(a);
32 
33   mpfr_init2 (res, p);
34   mpfr_init2 (ref, p);
35   mpfr_init2 (ab, mpfr_get_prec (a) +  mpfr_get_prec (b));
36   mpfr_init2 (cd, mpfr_get_prec (c) +  mpfr_get_prec (d));
37 
38   /* first check fmma */
39   inex_res = mpfr_fmma (res, a, b, c, d, rnd);
40   mpfr_mul (ab, a, b, rnd);
41   mpfr_mul (cd, c, d, rnd);
42   inex_ref = mpfr_add (ref, ab, cd, rnd);
43   if (! SAME_SIGN (inex_res, inex_ref) ||
44       mpfr_nan_p (res) || mpfr_nan_p (ref) ||
45       ! mpfr_equal_p (res, ref))
46     {
47       printf ("mpfr_fmma failed for p=%ld rnd=%s\n",
48               (long int) p, mpfr_print_rnd_mode (rnd));
49       printf ("a="); mpfr_dump (a);
50       printf ("b="); mpfr_dump (b);
51       printf ("c="); mpfr_dump (c);
52       printf ("d="); mpfr_dump (d);
53       printf ("Expected\n  ");
54       mpfr_dump (ref);
55       printf ("  with inex = %d\n", inex_ref);
56       printf ("Got\n  ");
57       mpfr_dump (res);
58       printf ("  with inex = %d\n", inex_res);
59       exit (1);
60     }
61 
62   /* then check fmms */
63   inex_res = mpfr_fmms (res, a, b, c, d, rnd);
64   mpfr_mul (ab, a, b, rnd);
65   mpfr_mul (cd, c, d, rnd);
66   inex_ref = mpfr_sub (ref, ab, cd, rnd);
67   if (! SAME_SIGN (inex_res, inex_ref) ||
68       mpfr_nan_p (res) || mpfr_nan_p (ref) ||
69       ! mpfr_equal_p (res, ref))
70     {
71       printf ("mpfr_fmms failed for p=%ld rnd=%s\n",
72               (long int) p, mpfr_print_rnd_mode (rnd));
73       printf ("a="); mpfr_dump (a);
74       printf ("b="); mpfr_dump (b);
75       printf ("c="); mpfr_dump (c);
76       printf ("d="); mpfr_dump (d);
77       printf ("Expected\n  ");
78       mpfr_dump (ref);
79       printf ("  with inex = %d\n", inex_ref);
80       printf ("Got\n  ");
81       mpfr_dump (res);
82       printf ("  with inex = %d\n", inex_res);
83       exit (1);
84     }
85 
86   mpfr_clear (ab);
87   mpfr_clear (cd);
88   mpfr_clear (res);
89   mpfr_clear (ref);
90 }
91 
92 static void
random_tests(void)93 random_tests (void)
94 {
95   mpfr_prec_t p;
96   int r;
97   mpfr_t a, b, c, d;
98 
99   for (p = MPFR_PREC_MIN; p <= 4096; p++)
100     {
101       mpfr_inits2 (p, a, b, c, d, (mpfr_ptr) 0);
102       mpfr_urandomb (a, RANDS);
103       mpfr_urandomb (b, RANDS);
104       mpfr_urandomb (c, RANDS);
105       mpfr_urandomb (d, RANDS);
106       RND_LOOP_NO_RNDF (r)
107         random_test (a, b, c, d, (mpfr_rnd_t) r);
108       mpfr_clears (a, b, c, d, (mpfr_ptr) 0);
109     }
110 }
111 
112 static void
zero_tests(void)113 zero_tests (void)
114 {
115   mpfr_exp_t emin, emax;
116   mpfr_t a, b, c, d, res;
117   int i, r;
118 
119   emin = mpfr_get_emin ();
120   emax = mpfr_get_emax ();
121   set_emin (MPFR_EMIN_MIN);
122   set_emax (MPFR_EMAX_MAX);
123 
124   mpfr_inits2 (GMP_NUMB_BITS, a, b, c, d, (mpfr_ptr) 0);
125   for (i = 0; i <= 4; i++)
126     {
127       switch (i)
128         {
129         case 0: case 1:
130           mpfr_set_ui (a, i, MPFR_RNDN);
131           break;
132         case 2:
133           mpfr_setmax (a, MPFR_EMAX_MAX);
134           break;
135         case 3:
136           mpfr_setmin (a, MPFR_EMIN_MIN);
137           break;
138         case 4:
139           mpfr_setmin (a, MPFR_EMIN_MIN+1);
140           break;
141         }
142       RND_LOOP (r)
143         {
144           int j, inex;
145           mpfr_flags_t flags;
146 
147           mpfr_set (b, a, MPFR_RNDN);
148           mpfr_set (c, a, MPFR_RNDN);
149           mpfr_neg (d, a, MPFR_RNDN);
150           /* We also want to test cases where the precision of the
151              result is twice the precision of each input, in case
152              add1sp.c and/or sub1sp.c could be involved. */
153           for (j = 1; j <= 2; j++)
154             {
155               mpfr_init2 (res, GMP_NUMB_BITS * j);
156               mpfr_clear_flags ();
157               inex = mpfr_fmma (res, a, b, c, d, (mpfr_rnd_t) r);
158               flags = __gmpfr_flags;
159               if (flags != 0 || inex != 0 || ! mpfr_zero_p (res) ||
160                   (r == MPFR_RNDD ? MPFR_IS_POS (res) : MPFR_IS_NEG (res)))
161                 {
162                   printf ("Error in zero_tests on i = %d, %s\n",
163                           i, mpfr_print_rnd_mode ((mpfr_rnd_t) r));
164                   printf ("Expected %c0, inex = 0\n",
165                           r == MPFR_RNDD ? '-' : '+');
166                   printf ("Got      ");
167                   if (MPFR_IS_POS (res))
168                     printf ("+");
169                   mpfr_out_str (stdout, 16, 0, res, MPFR_RNDN);
170                   printf (", inex = %d\n", inex);
171                   printf ("Expected flags:");
172                   flags_out (0);
173                   printf ("Got flags:     ");
174                   flags_out (flags);
175                   exit (1);
176                 }
177               mpfr_clear (res);
178             } /* j */
179         } /* r */
180     } /* i */
181   mpfr_clears (a, b, c, d, (mpfr_ptr) 0);
182 
183   set_emin (emin);
184   set_emax (emax);
185 }
186 
187 static void
max_tests(void)188 max_tests (void)
189 {
190   mpfr_exp_t emin, emax;
191   mpfr_t x, y1, y2;
192   int r;
193   int i, inex1, inex2;
194   mpfr_flags_t flags1, flags2;
195 
196   emin = mpfr_get_emin ();
197   emax = mpfr_get_emax ();
198   set_emin (MPFR_EMIN_MIN);
199   set_emax (MPFR_EMAX_MAX);
200 
201   mpfr_init2 (x, GMP_NUMB_BITS);
202   mpfr_setmax (x, MPFR_EMAX_MAX);
203   flags1 = MPFR_FLAGS_OVERFLOW | MPFR_FLAGS_INEXACT;
204   RND_LOOP (r)
205     {
206       /* We also want to test cases where the precision of the
207          result is twice the precision of each input, in case
208          add1sp.c and/or sub1sp.c could be involved. */
209       for (i = 1; i <= 2; i++)
210         {
211           mpfr_inits2 (GMP_NUMB_BITS * i, y1, y2, (mpfr_ptr) 0);
212           inex1 = mpfr_mul (y1, x, x, (mpfr_rnd_t) r);
213           mpfr_clear_flags ();
214           inex2 = mpfr_fmma (y2, x, x, x, x, (mpfr_rnd_t) r);
215           flags2 = __gmpfr_flags;
216           if (! (flags1 == flags2 && SAME_SIGN (inex1, inex2) &&
217                  mpfr_equal_p (y1, y2)))
218             {
219               printf ("Error in max_tests for %s\n",
220                       mpfr_print_rnd_mode ((mpfr_rnd_t) r));
221               printf ("Expected ");
222               mpfr_dump (y1);
223               printf ("  with inex = %d, flags =", inex1);
224               flags_out (flags1);
225               printf ("Got      ");
226               mpfr_dump (y2);
227               printf ("  with inex = %d, flags =", inex2);
228               flags_out (flags2);
229               exit (1);
230             }
231           mpfr_clears (y1, y2, (mpfr_ptr) 0);
232         } /* i */
233     } /* r */
234   mpfr_clear (x);
235 
236   set_emin (emin);
237   set_emax (emax);
238 }
239 
240 /* a^2 - (a+k)(a-k) = k^2 where a^2 overflows but k^2 usually doesn't.
241  * a^2 + cd where a^2 overflows and cd doesn't affect the overflow
242  * (and cd may even underflow).
243  */
244 static void
overflow_tests(void)245 overflow_tests (void)
246 {
247   mpfr_exp_t old_emax;
248   int i;
249 
250   old_emax = mpfr_get_emax ();
251 
252   for (i = 0; i < 40; i++)
253     {
254       mpfr_exp_t emax, exp_a;
255       mpfr_t a, k, c, d, z1, z2;
256       mpfr_rnd_t rnd;
257       mpfr_prec_t prec_a, prec_z;
258       int add = i & 1, inex, inex1, inex2;
259       mpfr_flags_t flags1, flags2;
260 
261       /* In most cases, we do the test with the maximum exponent. */
262       emax = i % 8 != 0 ? MPFR_EMAX_MAX : 64 + RAND_BOOL ();
263       set_emax (emax);
264       exp_a = emax/2 + 32;
265 
266       rnd = RND_RAND_NO_RNDF ();
267       prec_a = 64 + randlimb () % 100;
268       prec_z = MPFR_PREC_MIN + randlimb () % 160;
269 
270       mpfr_init2 (a, prec_a);
271       mpfr_urandom (a, RANDS, MPFR_RNDU);
272       mpfr_set_exp (a, exp_a);
273 
274       mpfr_init2 (k, prec_a - 32);
275       mpfr_urandom (k, RANDS, MPFR_RNDU);
276       mpfr_set_exp (k, exp_a - 32);
277 
278       mpfr_init2 (c, prec_a + 1);
279       inex = mpfr_add (c, a, k, MPFR_RNDN);
280       MPFR_ASSERTN (inex == 0);
281 
282       mpfr_init2 (d, prec_a);
283       inex = mpfr_sub (d, a, k, MPFR_RNDN);
284       MPFR_ASSERTN (inex == 0);
285       if (add)
286         mpfr_neg (d, d, MPFR_RNDN);
287 
288       mpfr_init2 (z1, prec_z);
289       mpfr_clear_flags ();
290       inex1 = mpfr_sqr (z1, k, rnd);
291       flags1 = __gmpfr_flags;
292 
293       mpfr_init2 (z2, prec_z);
294       mpfr_clear_flags ();
295       inex2 = add ?
296         mpfr_fmma (z2, a, a, c, d, rnd) :
297         mpfr_fmms (z2, a, a, c, d, rnd);
298       flags2 = __gmpfr_flags;
299 
300       if (! (flags1 == flags2 && SAME_SIGN (inex1, inex2) &&
301              mpfr_equal_p (z1, z2)))
302         {
303           printf ("Error 1 in overflow_tests for %s\n",
304                   mpfr_print_rnd_mode (rnd));
305           printf ("Expected ");
306           mpfr_dump (z1);
307           printf ("  with inex = %d, flags =", inex1);
308           flags_out (flags1);
309           printf ("Got      ");
310           mpfr_dump (z2);
311           printf ("  with inex = %d, flags =", inex2);
312           flags_out (flags2);
313           exit (1);
314         }
315 
316       /* c and d such that a^2 +/- cd ~= a^2 (overflow) */
317       mpfr_urandom (c, RANDS, MPFR_RNDU);
318       mpfr_set_exp (c, RAND_BOOL () ? exp_a - 2 : __gmpfr_emin);
319       if (RAND_BOOL ())
320         mpfr_neg (c, c, MPFR_RNDN);
321       mpfr_urandom (d, RANDS, MPFR_RNDU);
322       mpfr_set_exp (d, RAND_BOOL () ? exp_a - 2 : __gmpfr_emin);
323       if (RAND_BOOL ())
324         mpfr_neg (d, d, MPFR_RNDN);
325 
326       mpfr_clear_flags ();
327       inex1 = mpfr_sqr (z1, a, rnd);
328       flags1 = __gmpfr_flags;
329       MPFR_ASSERTN (flags1 == (MPFR_FLAGS_OVERFLOW | MPFR_FLAGS_INEXACT));
330 
331       mpfr_clear_flags ();
332       inex2 = add ?
333         mpfr_fmma (z2, a, a, c, d, rnd) :
334         mpfr_fmms (z2, a, a, c, d, rnd);
335       flags2 = __gmpfr_flags;
336 
337       if (! (flags1 == flags2 && SAME_SIGN (inex1, inex2) &&
338              mpfr_equal_p (z1, z2)))
339         {
340           printf ("Error 2 in overflow_tests for %s\n",
341                   mpfr_print_rnd_mode (rnd));
342           printf ("Expected ");
343           mpfr_dump (z1);
344           printf ("  with inex = %d, flags =", inex1);
345           flags_out (flags1);
346           printf ("Got      ");
347           mpfr_dump (z2);
348           printf ("  with inex = %d, flags =", inex2);
349           flags_out (flags2);
350           printf ("a="); mpfr_dump (a);
351           printf ("c="); mpfr_dump (c);
352           printf ("d="); mpfr_dump (d);
353           exit (1);
354         }
355 
356       mpfr_clears (a, k, c, d, z1, z2, (mpfr_ptr) 0);
357     }
358 
359   set_emax (old_emax);
360 }
361 
362 /* (1/2)x + (1/2)x = x tested near underflow */
363 static void
half_plus_half(void)364 half_plus_half (void)
365 {
366   mpfr_exp_t emin;
367   mpfr_t h, x1, x2, y;
368   int neg, r, i, inex;
369   mpfr_flags_t flags;
370 
371   emin = mpfr_get_emin ();
372   set_emin (MPFR_EMIN_MIN);
373   mpfr_inits2 (4, h, x1, (mpfr_ptr) 0);
374   mpfr_init2 (x2, GMP_NUMB_BITS);
375   mpfr_set_ui_2exp (h, 1, -1, MPFR_RNDN);
376 
377   for (mpfr_setmin (x1, __gmpfr_emin);
378        MPFR_GET_EXP (x1) < __gmpfr_emin + 2;
379        mpfr_nextabove (x1))
380     {
381       inex = mpfr_set (x2, x1, MPFR_RNDN);
382       MPFR_ASSERTN (inex == 0);
383       for (neg = 0; neg < 2; neg++)
384         {
385           RND_LOOP (r)
386             {
387               /* We also want to test cases where the precision of the
388                  result is twice the precision of each input, in case
389                  add1sp.c and/or sub1sp.c could be involved. */
390               for (i = 1; i <= 2; i++)
391                 {
392                   mpfr_init2 (y, GMP_NUMB_BITS * i);
393                   mpfr_clear_flags ();
394                   inex = mpfr_fmma (y, h, x2, h, x2, (mpfr_rnd_t) r);
395                   flags = __gmpfr_flags;
396                   if (! (flags == 0 && inex == 0 && mpfr_equal_p (y, x2)))
397                     {
398                       printf ("Error in half_plus_half for %s\n",
399                               mpfr_print_rnd_mode ((mpfr_rnd_t) r));
400                       printf ("Expected ");
401                       mpfr_dump (x2);
402                       printf ("  with inex = 0, flags =");
403                       flags_out (0);
404                       printf ("Got      ");
405                       mpfr_dump (y);
406                       printf ("  with inex = %d, flags =", inex);
407                       flags_out (flags);
408                       exit (1);
409                     }
410                   mpfr_clear (y);
411                 }
412             }
413           mpfr_neg (x2, x2, MPFR_RNDN);
414         }
415     }
416 
417   mpfr_clears (h, x1, x2, (mpfr_ptr) 0);
418   set_emin (emin);
419 }
420 
421 /* check that result has exponent in [emin, emax]
422    (see https://sympa.inria.fr/sympa/arc/mpfr/2017-04/msg00016.html)
423    Overflow detection in sub1.c was incorrect (only for UBF cases);
424    fixed in r11414. */
425 static void
bug20170405(void)426 bug20170405 (void)
427 {
428   mpfr_t x, y, z;
429 
430   mpfr_inits2 (866, x, y, z, (mpfr_ptr) 0);
431 
432   mpfr_set_str_binary (x, "-0.10010101110110001111000110010100011001111011110001010100010000111110001010111110100001000000011010001000010000101110000000001100001011000110010000100111001100000101110000000001001101101101010110000110100010010111011001101101010011111000101100000010001100010000011100000000011110100010111011101011000101101011110110001010011001101110011101100001111000011000000011000010101010000101001001010000111101100001000001011110011000110010001100001101101001001010000111100101000010111001001101010011001110110001000010101001100000101010110000100100100010101011111001001100010001010110011000000001011110011000110001000100101000111010010111111110010111001101110101010010101101010100111001011100101101010111010011001000001010011001010001101000111011010010100110011001111111000011101111001010111001001011011011110101101001100011010001010110011100001101100100001001100111010100010100E768635654");
433   mpfr_set_str_binary (y, "-0.11010001010111110010110101010011000010010011010011011101100100110000110101100110111010001001110101110000011101100010110100100011001101111010100011111001011100111101110101101001000101011110101101101011010100110010111111010011011100101111110011001001010101011101111100011101100001010010011000110010110101001110010001101111111001100100000101010100110011101101101010011001000110100001001100000010110010101111000110110000111011000110001000100100100101111110001111100101011100100100110111010000010110110001110010001001101000000110111000101000110101111110000110001110100010101111010110001111010111111111010011001001100110011000110010110011000101110001010001101000100010000110011101010010010011110100000111100000101100110001111010000100011111000001101111110100000011011110010100010010011111111000010110000000011010011001100110001110111111010111110000111110010110011001000010E768635576");
434   /* since emax = 1073741821, x^2-y^2 should overflow */
435   mpfr_fmms (z, x, x, y, y, MPFR_RNDN);
436   MPFR_ASSERTN(mpfr_inf_p (z) && mpfr_sgn (z) > 0);
437 
438   /* same test when z has a different precision */
439   mpfr_set_prec (z, 867);
440   mpfr_fmms (z, x, x, y, y, MPFR_RNDN);
441   MPFR_ASSERTN(mpfr_inf_p (z) && mpfr_sgn (z) > 0);
442 
443   mpfr_set_prec (x, 564);
444   mpfr_set_prec (y, 564);
445   mpfr_set_prec (z, 2256);
446   mpfr_set_str_binary (x, "1e-536870913");
447   mpfr_set_str_binary (y, "-1e-536870913");
448   mpfr_fmma (z, x, y, x, y, MPFR_RNDN);
449   /* we should get -0 as result */
450   MPFR_ASSERTN(mpfr_zero_p (z) && mpfr_signbit (z));
451 
452   mpfr_set_prec (x, 564);
453   mpfr_set_prec (y, 564);
454   mpfr_set_prec (z, 2256);
455   mpfr_set_str_binary (x, "1.10010000111100110011001101111111101000111001011000110100110010000101000100010001000000111100010000101001011011111001111000110101111100101111001100001100011101100100011110000000011000010110111100111000100101010001011111010111011001110010001011101111001011001110110000010000011100010001010001011100100110111110101001001111001011101111110011101110101010110100010010111011111100010101111100011110111001011111101110101101101110100101111010000101011110100000000110111101000001100001000100010110100111010011011010110011100111010000101110010101111001011100110101100001100e-737194993");
456   mpfr_set_str_binary (y, "-1.00101000100001001101011110100010110011101010011011010111100110101011111100000100101000111010111101100100110010001110011011100100110110000001011001000111101111101111110101100110111000000011000001101001010100010010001110001000011010000100111001001100101111111100010101110101001101101101111010100011011110001000010000010100011000011000010110101100000111111110111001100100100001101011111011100101110111000100101010110100010011101010110010100110100111000000100111101101101000000011110000100110100100011000010011110010001010000110100011111101101101110001110001101101010e-737194903");
457   mpfr_fmma (z, x, y, x, y, MPFR_RNDN);
458   /* we should get -0 as result */
459   MPFR_ASSERTN(mpfr_zero_p (z) && mpfr_signbit (z));
460 
461   mpfr_set_prec (x, 2);
462   mpfr_set_prec (y, 2);
463   mpfr_set_prec (z, 2);
464   /* (a+i*b)*(c+i*d) with:
465      a=0.10E1
466      b=0.10E-536870912
467      c=0.10E-536870912
468      d=0.10E1 */
469   mpfr_set_str_binary (x, "0.10E1"); /* x = a = d */
470   mpfr_set_str_binary (y, "0.10E-536870912"); /* y = b = c */
471   /* real part is a*c-b*d = x*y-y*x */
472   mpfr_fmms (z, x, y, y, x, MPFR_RNDN);
473   MPFR_ASSERTN(mpfr_zero_p (z) && !mpfr_signbit (z));
474   /* imaginary part is a*d+b*c = x*x+y*y */
475   mpfr_fmma (z, x, x, y, y, MPFR_RNDN);
476   MPFR_ASSERTN(mpfr_cmp_ui (z, 1) == 0);
477   mpfr_fmma (z, y, y, x, x, MPFR_RNDN);
478   MPFR_ASSERTN(mpfr_cmp_ui (z, 1) == 0);
479 
480   mpfr_clears (x, y, z, (mpfr_ptr) 0);
481 }
482 
483 static void
underflow_tests(void)484 underflow_tests (void)
485 {
486   mpfr_t x, y, z;
487   mpfr_prec_t p;
488   mpfr_exp_t emin;
489 
490   emin = mpfr_get_emin ();
491   set_emin (-17);
492   for (p = MPFR_PREC_MIN; p <= 1024; p++)
493     {
494       mpfr_inits2 (p, x, y, (mpfr_ptr) 0);
495       mpfr_init2 (z, p + 1);
496       mpfr_set_str_binary (x, "1e-10");
497       mpfr_set_str_binary (y, "1e-11");
498       mpfr_clear_underflow ();
499       mpfr_fmms (z, x, x, y, y, MPFR_RNDN);
500       /* the exact result is 2^-20-2^-22, and should underflow */
501       MPFR_ASSERTN(mpfr_underflow_p ());
502       MPFR_ASSERTN(mpfr_zero_p (z));
503       MPFR_ASSERTN(mpfr_signbit (z) == 0);
504       mpfr_clears (x, y, z, (mpfr_ptr) 0);
505     }
506   set_emin (emin);
507 }
508 
509 static void
bug20180604(void)510 bug20180604 (void)
511 {
512   mpfr_t x, y, yneg, z;
513   mpfr_exp_t emin;
514   int ret;
515 
516   emin = mpfr_get_emin ();
517   set_emin (-1073741821);
518   mpfr_inits2 (564, x, y, yneg, (mpfr_ptr) 0);
519   mpfr_init2 (z, 2256);
520   mpfr_set_str_binary (x, "1.10010000111100110011001101111111101000111001011000110100110010000101000100010001000000111100010000101001011011111001111000110101111100101111001100001100011101100100011110000000011000010110111100111000100101010001011111010111011001110010001011101111001011001110110000010000011100010001010001011100100110111110101001001111001011101111110011101110101010110100010010111011111100010101111100011110111001011111101110101101101110100101111010000101011110100000000110111101000001100001000100010110100111010011011010110011100111010000101110010101111001011100110101100001100E-737194993");
521   mpfr_set_str_binary (y, "-1.00101000100001001101011110100010110011101010011011010111100110101011111100000100101000111010111101100100110010001110011011100100110110000001011001000111101111101111110101100110111000000011000001101001010100010010001110001000011010000100111001001100101111111100010101110101001101101101111010100011011110001000010000010100011000011000010110101100000111111110111001100100100001101011111011100101110111000100101010110100010011101010110010100110100111000000100111101101101000000011110000100110100100011000010011110010001010000110100011111101101101110001110001101101010E-737194903");
522 
523   mpfr_clear_underflow ();
524   ret = mpfr_fmms (z, x, x, y, y, MPFR_RNDN);
525   MPFR_ASSERTN(mpfr_underflow_p ());
526   MPFR_ASSERTN(mpfr_zero_p (z));
527   MPFR_ASSERTN(mpfr_signbit (z) == 1);
528   MPFR_ASSERTN(ret > 0);
529 
530   mpfr_clear_underflow ();
531   ret = mpfr_fmms (z, y, y, x, x, MPFR_RNDN);
532   MPFR_ASSERTN(mpfr_underflow_p ());
533   MPFR_ASSERTN(mpfr_zero_p (z));
534   MPFR_ASSERTN(mpfr_signbit (z) == 0);
535   MPFR_ASSERTN(ret < 0);
536 
537   mpfr_neg (yneg, y, MPFR_RNDN);
538   mpfr_clear_underflow ();
539   ret = mpfr_fmms (z, x, x, y, yneg, MPFR_RNDN);
540   MPFR_ASSERTN(mpfr_underflow_p ());
541   MPFR_ASSERTN(mpfr_zero_p (z));
542   MPFR_ASSERTN(mpfr_signbit (z) == 0);
543   MPFR_ASSERTN(ret < 0);
544 
545   mpfr_clear_underflow ();
546   ret = mpfr_fmms (z, y, yneg, x, x, MPFR_RNDN);
547   MPFR_ASSERTN(mpfr_underflow_p ());
548   MPFR_ASSERTN(mpfr_zero_p (z));
549   MPFR_ASSERTN(mpfr_signbit (z) == 1);
550   MPFR_ASSERTN(ret > 0);
551 
552   mpfr_clears (x, y, yneg, z, (mpfr_ptr) 0);
553   set_emin (emin);
554 }
555 
556 /* this bug was discovered from mpc_mul */
557 static void
bug20200206(void)558 bug20200206 (void)
559 {
560   mpfr_exp_t emin = mpfr_get_emin ();
561   mpfr_t xre, xim, yre, yim, zre;
562 
563   set_emin (-1073);
564   mpfr_inits2 (53, xre, xim, yre, yim, zre, (mpfr_ptr) 0);
565   mpfr_set_str (xre, "-0x8.294611b331c8p-904", 16, MPFR_RNDN);
566   mpfr_set_str (xim, "-0x1.859278c2992fap-676", 16, MPFR_RNDN);
567   mpfr_set_str (yre, "0x9.ac54802a95f8p-820", 16, MPFR_RNDN);
568   mpfr_set_str (yim, "0x3.17e59e7612aap-412", 16, MPFR_RNDN);
569   mpfr_fmms (zre, xre, yre, xim, yim, MPFR_RNDN);
570   if (mpfr_regular_p (zre) && mpfr_get_exp (zre) < -1073)
571     {
572       printf ("Error, mpfr_fmms returns an out-of-range exponent:\n");
573       mpfr_dump (zre);
574       exit (1);
575     }
576   mpfr_clears (xre, xim, yre, yim, zre, (mpfr_ptr) 0);
577   set_emin (emin);
578 }
579 
580 /* check for integer overflow (see bug fixed in r13798) */
581 static void
extreme_underflow(void)582 extreme_underflow (void)
583 {
584   mpfr_t x, y, z;
585   mpfr_exp_t emin = mpfr_get_emin ();
586 
587   set_emin (MPFR_EMIN_MIN);
588   mpfr_inits2 (64, x, y, z, (mpfr_ptr) 0);
589   mpfr_set_ui_2exp (x, 1, MPFR_EMIN_MIN - 1, MPFR_RNDN);
590   mpfr_set (y, x, MPFR_RNDN);
591   mpfr_nextabove (x);
592   mpfr_clear_flags ();
593   mpfr_fmms (z, x, x, y, y, MPFR_RNDN);
594   MPFR_ASSERTN (__gmpfr_flags == (MPFR_FLAGS_UNDERFLOW | MPFR_FLAGS_INEXACT));
595   MPFR_ASSERTN (MPFR_IS_ZERO (z) && MPFR_IS_POS (z));
596   mpfr_clears (x, y, z, (mpfr_ptr) 0);
597   set_emin (emin);
598 }
599 
600 /* Test double-rounding cases in mpfr_set_1_2, which is called when
601    all the precisions are the same. With set.c before r13347, this
602    triggers errors for neg=0. */
603 static void
double_rounding(void)604 double_rounding (void)
605 {
606   int p;
607 
608   for (p = 4; p < 4 * GMP_NUMB_BITS; p++)
609     {
610       mpfr_t a, b, c, d, z1, z2;
611       int neg;
612 
613       mpfr_inits2 (p, a, b, c, d, z1, z2, (mpfr_ptr) 0);
614       /* Choose a, b, c, d such that a*b = 2^p and c*d = 1 + epsilon */
615       mpfr_set_ui (a, 2, MPFR_RNDN);
616       mpfr_set_ui_2exp (b, 1, p - 1, MPFR_RNDN);
617       mpfr_set_ui (c, 1, MPFR_RNDN);
618       mpfr_nextabove (c);
619       /* c = 1 + ulp(1) = 1 + 2 * ulp(1/2) */
620 
621       for (neg = 0; neg <= 1; neg++)
622         {
623           int inex1, inex2;
624 
625           /* Set d = 1 - (1 + neg) * ulp(1/2), thus
626            * c*d = 1 + (1 - neg) * ulp(1/2) - 2 * (1 + neg) * ulp(1/2)^2,
627            * so that a*b + c*d rounds to 2^p + 1 and epsilon has the
628            * same sign as (-1)^neg.
629            */
630           mpfr_set_ui (d, 1, MPFR_RNDN);
631           mpfr_nextbelow (d);
632           mpfr_set_ui_2exp (z1, 1, p, MPFR_RNDN);
633           if (neg)
634             {
635               mpfr_nextbelow (d);
636               inex1 = -1;
637             }
638           else
639             {
640               mpfr_nextabove (z1);
641               inex1 = 1;
642             }
643 
644           inex2 = mpfr_fmma (z2, a, b, c, d, MPFR_RNDN);
645           if (!(mpfr_equal_p (z1, z2) && SAME_SIGN (inex1, inex2)))
646             {
647               printf ("Error in double_rounding for precision %d, neg=%d\n",
648                       p, neg);
649               printf ("Expected ");
650               mpfr_dump (z1);
651               printf ("with inex = %d\n", inex1);
652               printf ("Got      ");
653               mpfr_dump (z2);
654               printf ("with inex = %d\n", inex2);
655               exit (1);
656             }
657         }
658 
659       mpfr_clears (a, b, c, d, z1, z2, (mpfr_ptr) 0);
660     }
661 }
662 
663 int
main(int argc,char * argv[])664 main (int argc, char *argv[])
665 {
666   tests_start_mpfr ();
667 
668   bug20200206 ();
669   bug20180604 ();
670   underflow_tests ();
671   random_tests ();
672   zero_tests ();
673   max_tests ();
674   overflow_tests ();
675   half_plus_half ();
676   bug20170405 ();
677   double_rounding ();
678   extreme_underflow ();
679 
680   tests_end_mpfr ();
681   return 0;
682 }
683