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