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