diff --git a/mpfr-4.0.1-cummulative-patch.patch b/mpfr-4.0.1-cummulative-patch.patch deleted file mode 100644 index f6bfdb7..0000000 --- a/mpfr-4.0.1-cummulative-patch.patch +++ /dev/null @@ -1,1974 +0,0 @@ -diff -Naurd mpfr-4.0.1-a/PATCHES mpfr-4.0.1-b/PATCHES ---- mpfr-4.0.1-a/PATCHES 2018-04-27 12:40:46.838268769 +0000 -+++ mpfr-4.0.1-b/PATCHES 2018-04-27 12:40:46.870268475 +0000 -@@ -0,0 +1 @@ -+sub1sp1n-reuse -diff -Naurd mpfr-4.0.1-a/VERSION mpfr-4.0.1-b/VERSION ---- mpfr-4.0.1-a/VERSION 2018-02-07 12:50:31.000000000 +0000 -+++ mpfr-4.0.1-b/VERSION 2018-04-27 12:40:46.870268475 +0000 -@@ -1 +1 @@ --4.0.1 -+4.0.1-p1 -diff -Naurd mpfr-4.0.1-a/src/mpfr.h mpfr-4.0.1-b/src/mpfr.h ---- mpfr-4.0.1-a/src/mpfr.h 2018-02-07 12:50:31.000000000 +0000 -+++ mpfr-4.0.1-b/src/mpfr.h 2018-04-27 12:40:46.870268475 +0000 -@@ -27,7 +27,7 @@ - #define MPFR_VERSION_MAJOR 4 - #define MPFR_VERSION_MINOR 0 - #define MPFR_VERSION_PATCHLEVEL 1 --#define MPFR_VERSION_STRING "4.0.1" -+#define MPFR_VERSION_STRING "4.0.1-p1" - - /* User macros: - MPFR_USE_FILE: Define it to make MPFR define functions dealing -diff -Naurd mpfr-4.0.1-a/src/sub1sp.c mpfr-4.0.1-b/src/sub1sp.c ---- mpfr-4.0.1-a/src/sub1sp.c 2018-01-09 12:30:58.000000000 +0000 -+++ mpfr-4.0.1-b/src/sub1sp.c 2018-04-27 12:40:46.858268585 +0000 -@@ -375,13 +375,15 @@ - } - else /* cases (a), (c), (d) and (e) */ - { -- ap[0] = -MPFR_LIMB_ONE; - /* rb=1 in case (e) and case (c) */ - rb = d > GMP_NUMB_BITS + 1 - || (d == GMP_NUMB_BITS + 1 && cp[0] == MPFR_LIMB_HIGHBIT); - /* sb = 1 in case (d) and (e) */ - sb = d > GMP_NUMB_BITS + 1 - || (d == GMP_NUMB_BITS + 1 && cp[0] > MPFR_LIMB_HIGHBIT); -+ /* Warning: only set ap[0] last, otherwise in case ap=cp, -+ the above comparisons involving cp[0] would be wrong */ -+ ap[0] = -MPFR_LIMB_ONE; - } - } - } -diff -Naurd mpfr-4.0.1-a/src/version.c mpfr-4.0.1-b/src/version.c ---- mpfr-4.0.1-a/src/version.c 2018-02-07 12:50:31.000000000 +0000 -+++ mpfr-4.0.1-b/src/version.c 2018-04-27 12:40:46.870268475 +0000 -@@ -25,5 +25,5 @@ - const char * - mpfr_get_version (void) - { -- return "4.0.1"; -+ return "4.0.1-p1"; - } -diff -Naurd mpfr-4.0.1-a/tests/tsub.c mpfr-4.0.1-b/tests/tsub.c ---- mpfr-4.0.1-a/tests/tsub.c 2018-01-09 12:30:58.000000000 +0000 -+++ mpfr-4.0.1-b/tests/tsub.c 2018-04-27 12:40:46.858268585 +0000 -@@ -22,12 +22,13 @@ - - #include "mpfr-test.h" - --#ifdef CHECK_EXTERNAL - static int - test_sub (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) - { -+#ifdef CHECK_EXTERNAL - int res; - int ok = rnd_mode == MPFR_RNDN && mpfr_number_p (b) && mpfr_number_p (c); -+ - if (ok) - { - mpfr_print_raw (b); -@@ -42,10 +43,69 @@ - printf ("\n"); - } - return res; --} --#else --#define test_sub mpfr_sub -+#else /* reuse test */ -+ int inex; -+ -+ inex = mpfr_sub (a, b, c, rnd_mode); -+ -+ if (a != b && a != c && ! MPFR_IS_NAN (a)) -+ { -+ mpfr_t t; -+ int reuse_b, reuse_c, inex_r; -+ -+ reuse_b = MPFR_PREC (a) == MPFR_PREC (b); -+ reuse_c = MPFR_PREC (a) == MPFR_PREC (c); -+ -+ if (reuse_b || reuse_c) -+ mpfr_init2 (t, MPFR_PREC (a)); -+ -+ if (reuse_b) -+ { -+ mpfr_set (t, b, MPFR_RNDN); -+ inex_r = mpfr_sub (t, t, c, rnd_mode); -+ if (!(mpfr_equal_p (t, a) && SAME_SIGN (inex_r, inex))) -+ { -+ printf ("reuse of b error in b - c in %s for\n", -+ mpfr_print_rnd_mode (rnd_mode)); -+ printf ("b = "); -+ mpfr_dump (b); -+ printf ("c = "); -+ mpfr_dump (c); -+ printf ("Expected "); mpfr_dump (a); -+ printf (" with inex = %d\n", inex); -+ printf ("Got "); mpfr_dump (t); -+ printf (" with inex = %d\n", inex_r); -+ exit (1); -+ } -+ } -+ -+ if (reuse_c) -+ { -+ mpfr_set (t, c, MPFR_RNDN); -+ inex_r = mpfr_sub (t, b, t, rnd_mode); -+ if (!(mpfr_equal_p (t, a) && SAME_SIGN (inex_r, inex))) -+ { -+ printf ("reuse of c error in b - c in %s for\n", -+ mpfr_print_rnd_mode (rnd_mode)); -+ printf ("b = "); -+ mpfr_dump (b); -+ printf ("c = "); -+ mpfr_dump (c); -+ printf ("Expected "); mpfr_dump (a); -+ printf (" with inex = %d\n", inex); -+ printf ("Got "); mpfr_dump (t); -+ printf (" with inex = %d\n", inex_r); -+ exit (1); -+ } -+ } -+ -+ if (reuse_b || reuse_c) -+ mpfr_clear (t); -+ } -+ -+ return inex; - #endif -+} - - static void - check_diverse (void) -@@ -940,6 +1000,80 @@ - } - } - -+/* Fails with r12281: "reuse of c error in b - c in MPFR_RNDN". */ -+static void -+bug20180217 (void) -+{ -+ mpfr_t x, y, z1, z2; -+ int r, p, d, i, inex1, inex2; -+ -+ for (p = 3; p <= 3 + 4 * GMP_NUMB_BITS; p++) -+ { -+ mpfr_inits2 (p, x, y, z1, z2, (mpfr_ptr) 0); -+ for (d = p; d <= p+4; d++) -+ { -+ mpfr_set_ui (x, 1, MPFR_RNDN); -+ mpfr_set_ui_2exp (y, 1, -d, MPFR_RNDN); -+ for (i = 0; i < 3; i++) -+ { -+ RND_LOOP_NO_RNDF (r) -+ { -+ mpfr_set (z1, x, MPFR_RNDN); -+ if (d == p) -+ { -+ mpfr_nextbelow (z1); -+ if (i == 0) -+ inex1 = 0; -+ else if (r == MPFR_RNDD || r == MPFR_RNDZ || -+ (r == MPFR_RNDN && i > 1)) -+ { -+ mpfr_nextbelow (z1); -+ inex1 = -1; -+ } -+ else -+ inex1 = 1; -+ } -+ else if (r == MPFR_RNDD || r == MPFR_RNDZ || -+ (r == MPFR_RNDN && d == p+1 && i > 0)) -+ { -+ mpfr_nextbelow (z1); -+ inex1 = -1; -+ } -+ else -+ inex1 = 1; -+ inex2 = test_sub (z2, x, y, (mpfr_rnd_t) r); -+ if (!(mpfr_equal_p (z1, z2) && SAME_SIGN (inex1, inex2))) -+ { -+ printf ("Error in bug20180217 with " -+ "p=%d, d=%d, i=%d, %s\n", p, d, i, -+ mpfr_print_rnd_mode ((mpfr_rnd_t) r)); -+ printf ("x = "); -+ mpfr_dump (x); -+ printf ("y = "); -+ mpfr_dump (y); -+ printf ("Expected "); mpfr_dump (z1); -+ printf (" with inex = %d\n", inex1); -+ printf ("Got "); mpfr_dump (z2); -+ printf (" with inex = %d\n", inex2); -+ exit (1); -+ } -+ } -+ if (i == 0) -+ mpfr_nextabove (y); -+ else -+ { -+ if (p < 6) -+ break; -+ mpfr_nextbelow (y); -+ mpfr_mul_ui (y, y, 25, MPFR_RNDD); -+ mpfr_div_2ui (y, y, 4, MPFR_RNDN); -+ } -+ } -+ } -+ mpfr_clears (x, y, z1, z2, (mpfr_ptr) 0); -+ } -+} -+ - #define TEST_FUNCTION test_sub - #define TWO_ARGS - #define RAND_FUNCTION(x) mpfr_random2(x, MPFR_LIMB_SIZE (x), randlimb () % 100, RANDS) -@@ -962,6 +1096,7 @@ - check_inexact (); - check_max_almosteven (); - bug_ddefour (); -+ bug20180217 (); - for (p=2; p<200; p++) - for (i=0; i<50; i++) - check_two_sum (p); -diff -Naurd mpfr-4.0.1-a/tests/tsub1sp.c mpfr-4.0.1-b/tests/tsub1sp.c ---- mpfr-4.0.1-a/tests/tsub1sp.c 2018-01-09 12:30:58.000000000 +0000 -+++ mpfr-4.0.1-b/tests/tsub1sp.c 2018-04-27 12:40:46.858268585 +0000 -@@ -284,6 +284,91 @@ - } - } - -+static void -+coverage (void) -+{ -+ mpfr_t a, b, c, d, u; -+ int inex; -+ -+ /* coverage test in mpfr_sub1sp: case d=1, limb > MPFR_LIMB_HIGHBIT, RNDF -+ and also RNDZ */ -+ mpfr_init2 (a, 3 * GMP_NUMB_BITS); -+ mpfr_init2 (b, 3 * GMP_NUMB_BITS); -+ mpfr_init2 (c, 3 * GMP_NUMB_BITS); -+ mpfr_init2 (d, 3 * GMP_NUMB_BITS); -+ mpfr_init2 (u, 3 * GMP_NUMB_BITS); -+ mpfr_set_ui (b, 1, MPFR_RNDN); -+ mpfr_nextbelow (b); /* b = 1 - 2^(-p) */ -+ mpfr_set_prec (c, GMP_NUMB_BITS); -+ mpfr_set_ui_2exp (c, 1, -1, MPFR_RNDN); -+ mpfr_nextbelow (c); -+ mpfr_nextbelow (c); /* c = 1/2 - 2*2^(-GMP_NUMB_BITS-1) */ -+ mpfr_prec_round (c, 3 * GMP_NUMB_BITS, MPFR_RNDN); -+ mpfr_nextbelow (c); /* c = 1/2 - 2*2^(-GMP_NUMB_BITS-1) - 2^(-p-1) */ -+ /* b-c = c */ -+ mpfr_sub (a, b, c, MPFR_RNDF); -+ mpfr_sub (d, b, c, MPFR_RNDD); -+ mpfr_sub (u, b, c, MPFR_RNDU); -+ /* check a = d or u */ -+ MPFR_ASSERTN(mpfr_equal_p (a, d) || mpfr_equal_p (a, u)); -+ -+ /* coverage test in mpfr_sub1sp: case d=p, RNDN, sb = 0, significand of b -+ is even but b<>2^e, (case 1e) */ -+ mpfr_set_prec (a, 3 * GMP_NUMB_BITS); -+ mpfr_set_prec (b, 3 * GMP_NUMB_BITS); -+ mpfr_set_prec (c, 3 * GMP_NUMB_BITS); -+ mpfr_set_ui (b, 1, MPFR_RNDN); -+ mpfr_nextabove (b); -+ mpfr_nextabove (b); -+ mpfr_set_ui_2exp (c, 1, -3 * GMP_NUMB_BITS, MPFR_RNDN); -+ inex = mpfr_sub (a, b, c, MPFR_RNDN); -+ MPFR_ASSERTN(inex > 0); -+ MPFR_ASSERTN(mpfr_equal_p (a, b)); -+ -+ mpfr_clear (a); -+ mpfr_clear (b); -+ mpfr_clear (c); -+ mpfr_clear (d); -+ mpfr_clear (u); -+} -+ -+/* bug in mpfr_sub1sp1n, made generic */ -+static void -+bug20180217 (mpfr_prec_t pmax) -+{ -+ mpfr_t a, b, c; -+ int inex; -+ mpfr_prec_t p; -+ -+ for (p = MPFR_PREC_MIN; p <= pmax; p++) -+ { -+ mpfr_init2 (a, p); -+ mpfr_init2 (b, p); -+ mpfr_init2 (c, p); -+ mpfr_set_ui (b, 1, MPFR_RNDN); /* b = 1 */ -+ mpfr_set_ui_2exp (c, 1, -p-1, MPFR_RNDN); /* c = 2^(-p-1) */ -+ /* a - b = 1 - 2^(-p-1) and should be rounded to 1 (case 2f of -+ mpfr_sub1sp) */ -+ inex = mpfr_sub (a, b, c, MPFR_RNDN); -+ MPFR_ASSERTN(inex > 0); -+ MPFR_ASSERTN(mpfr_cmp_ui (a, 1) == 0); -+ /* check also when a=b */ -+ mpfr_set_ui (a, 1, MPFR_RNDN); -+ inex = mpfr_sub (a, a, c, MPFR_RNDN); -+ MPFR_ASSERTN(inex > 0); -+ MPFR_ASSERTN(mpfr_cmp_ui (a, 1) == 0); -+ /* and when a=c */ -+ mpfr_set_ui (b, 1, MPFR_RNDN); /* b = 1 */ -+ mpfr_set_ui_2exp (a, 1, -p-1, MPFR_RNDN); -+ inex = mpfr_sub (a, b, a, MPFR_RNDN); -+ MPFR_ASSERTN(inex > 0); -+ MPFR_ASSERTN(mpfr_cmp_ui (a, 1) == 0); -+ mpfr_clear (a); -+ mpfr_clear (b); -+ mpfr_clear (c); -+ } -+} -+ - int - main (void) - { -@@ -291,6 +376,8 @@ - - tests_start_mpfr (); - -+ bug20180217 (1024); -+ coverage (); - compare_sub_sub1sp (); - test20170208 (); - bug20170109 (); -diff -Naurd mpfr-4.0.1-a/PATCHES mpfr-4.0.1-b/PATCHES ---- mpfr-4.0.1-a/PATCHES 2018-04-27 12:45:53.139452673 +0000 -+++ mpfr-4.0.1-b/PATCHES 2018-04-27 12:45:53.171452379 +0000 -@@ -0,0 +1 @@ -+fma -diff -Naurd mpfr-4.0.1-a/VERSION mpfr-4.0.1-b/VERSION ---- mpfr-4.0.1-a/VERSION 2018-04-27 12:40:46.870268475 +0000 -+++ mpfr-4.0.1-b/VERSION 2018-04-27 12:45:53.171452379 +0000 -@@ -1 +1 @@ --4.0.1-p1 -+4.0.1-p2 -diff -Naurd mpfr-4.0.1-a/src/fma.c mpfr-4.0.1-b/src/fma.c ---- mpfr-4.0.1-a/src/fma.c 2018-01-09 12:30:58.000000000 +0000 -+++ mpfr-4.0.1-b/src/fma.c 2018-04-27 12:45:53.159452489 +0000 -@@ -225,194 +225,73 @@ - - if (MPFR_IS_INF (u)) /* overflow */ - { -+ int sign_u = MPFR_SIGN (u); -+ - MPFR_LOG_MSG (("Overflow on x*y\n", 0)); -+ MPFR_GROUP_CLEAR (group); /* we no longer need u */ - - /* Let's eliminate the obvious case where x*y and z have the - same sign. No possible cancellation -> real overflow. - Also, we know that |z| < 2^emax. If E(x) + E(y) >= emax+3, -- then |x*y| >= 2^(emax+1), and |x*y + z| >= 2^emax. This case -+ then |x*y| >= 2^(emax+1), and |x*y + z| > 2^emax. This case - is also an overflow. */ -- if (MPFR_SIGN (u) == MPFR_SIGN (z) || e >= __gmpfr_emax + 3) -+ if (sign_u == MPFR_SIGN (z) || e >= __gmpfr_emax + 3) - { -- MPFR_GROUP_CLEAR (group); - MPFR_SAVE_EXPO_FREE (expo); -- return mpfr_overflow (s, rnd_mode, MPFR_SIGN (z)); -+ return mpfr_overflow (s, rnd_mode, sign_u); - } -- -- /* E(x) + E(y) <= emax+2, therefore |x*y| < 2^(emax+2), and -- (x/4)*y does not overflow (let's recall that the result -- is exact with an unbounded exponent range). It does not -- underflow either, because x*y overflows and the exponent -- range is large enough. */ -- inexact = mpfr_div_2ui (u, x, 2, MPFR_RNDN); -- MPFR_ASSERTN (inexact == 0); -- inexact = mpfr_mul (u, u, y, MPFR_RNDN); -- MPFR_ASSERTN (inexact == 0); -- -- /* Now, we need to add z/4... But it may underflow! */ -- { -- mpfr_t zo4; -- mpfr_srcptr zz; -- MPFR_BLOCK_DECL (flags); -- -- if (MPFR_GET_EXP (u) > MPFR_GET_EXP (z) && -- MPFR_GET_EXP (u) - MPFR_GET_EXP (z) > MPFR_PREC (u)) -- { -- /* |z| < ulp(u)/2, therefore one can use z instead of z/4. */ -- zz = z; -- } -- else -- { -- mpfr_init2 (zo4, MPFR_PREC (z)); -- if (mpfr_div_2ui (zo4, z, 2, MPFR_RNDZ)) -- { -- /* The division by 4 underflowed! */ -- MPFR_ASSERTN (0); /* TODO... */ -- } -- zz = zo4; -- } -- -- /* Let's recall that u = x*y/4 and zz = z/4 (or z if the -- following addition would give the same result). */ -- MPFR_BLOCK (flags, inexact = mpfr_add (s, u, zz, rnd_mode)); -- /* u and zz have different signs, so that an overflow -- is not possible. But an underflow is theoretically -- possible! */ -- if (MPFR_UNDERFLOW (flags)) -- { -- MPFR_ASSERTN (zz != z); -- MPFR_ASSERTN (0); /* TODO... */ -- mpfr_clears (zo4, u, (mpfr_ptr) 0); -- } -- else -- { -- int inex2; -- -- if (zz != z) -- mpfr_clear (zo4); -- MPFR_GROUP_CLEAR (group); -- MPFR_ASSERTN (! MPFR_OVERFLOW (flags)); -- inex2 = mpfr_mul_2ui (s, s, 2, rnd_mode); -- if (inex2) /* overflow */ -- { -- inexact = inex2; -- MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags); -- } -- goto end; -- } -- } - } -- else /* underflow: one has |xy| < 2^(emin-1). */ -+ else /* underflow: one has |x*y| < 2^(emin-1). */ - { -- unsigned long scale = 0; -- mpfr_t scaled_z; -- mpfr_srcptr new_z; -- mpfr_exp_t diffexp; -- mpfr_prec_t pzs; -- int xy_underflows; -- - MPFR_LOG_MSG (("Underflow on x*y\n", 0)); - -- /* Let's scale z so that ulp(z) > 2^emin and ulp(s) > 2^emin -- (the + 1 on MPFR_PREC (s) is necessary because the exponent -- of the result can be EXP(z) - 1). */ -- diffexp = MPFR_GET_EXP (z) - __gmpfr_emin; -- pzs = MAX (MPFR_PREC (z), MPFR_PREC (s) + 1); -- MPFR_LOG_MSG (("diffexp=%" MPFR_EXP_FSPEC "d pzs=%Pd\n", -- diffexp, pzs)); -- if (diffexp <= pzs) -- { -- mpfr_uexp_t uscale; -- mpfr_t scaled_v; -- MPFR_BLOCK_DECL (flags); -- -- uscale = (mpfr_uexp_t) pzs - diffexp + 1; -- MPFR_ASSERTN (uscale > 0); -- MPFR_ASSERTN (uscale <= ULONG_MAX); -- scale = uscale; -- mpfr_init2 (scaled_z, MPFR_PREC (z)); -- inexact = mpfr_mul_2ui (scaled_z, z, scale, MPFR_RNDN); -- MPFR_ASSERTN (inexact == 0); /* TODO: overflow case */ -- new_z = scaled_z; -- /* Now we need to recompute u = xy * 2^scale. */ -- MPFR_BLOCK (flags, -- if (MPFR_GET_EXP (x) < MPFR_GET_EXP (y)) -- { -- mpfr_init2 (scaled_v, precx); -- mpfr_mul_2ui (scaled_v, x, scale, MPFR_RNDN); -- mpfr_mul (u, scaled_v, y, MPFR_RNDN); -- } -- else -- { -- mpfr_init2 (scaled_v, precy); -- mpfr_mul_2ui (scaled_v, y, scale, MPFR_RNDN); -- mpfr_mul (u, x, scaled_v, MPFR_RNDN); -- }); -- mpfr_clear (scaled_v); -- MPFR_ASSERTN (! MPFR_OVERFLOW (flags)); -- xy_underflows = MPFR_UNDERFLOW (flags); -- } -- else -- { -- new_z = z; -- xy_underflows = 1; -- } -- -- MPFR_LOG_MSG (("scale=%lu xy_underflows=%d\n", -- scale, xy_underflows)); -- -- if (xy_underflows) -+ /* Easy cases: when 2^(emin-1) <= 1/2 * min(ulp(z),ulp(s)), -+ one can replace x*y by sign(x*y) * 2^(emin-1). Note that -+ this is even true in case of equality for MPFR_RNDN thanks -+ to the even-rounding rule. -+ The + 1 on MPFR_PREC (s) is necessary because the exponent -+ of the result can be EXP(z) - 1. */ -+ if (MPFR_GET_EXP (z) - __gmpfr_emin >= -+ MAX (MPFR_PREC (z), MPFR_PREC (s) + 1)) - { -- /* Let's replace xy by sign(xy) * 2^(emin-1). */ - MPFR_PREC (u) = MPFR_PREC_MIN; - mpfr_setmin (u, __gmpfr_emin); - MPFR_SET_SIGN (u, MPFR_MULT_SIGN (MPFR_SIGN (x), - MPFR_SIGN (y))); -+ mpfr_clear_flags (); -+ goto add; - } - -- { -- MPFR_BLOCK_DECL (flags); -+ MPFR_GROUP_CLEAR (group); /* we no longer need u */ -+ } - -- MPFR_BLOCK (flags, inexact = mpfr_add (s, u, new_z, rnd_mode)); -- MPFR_LOG_MSG (("inexact=%d\n", inexact)); -- MPFR_GROUP_CLEAR (group); -- if (scale != 0) -- { -- int inex2; -+ /* Let's use UBF to resolve the overflow/underflow issues. */ -+ { -+ mpfr_ubf_t uu; -+ mp_size_t un; -+ mpfr_limb_ptr up; -+ MPFR_TMP_DECL(marker); - -- mpfr_clear (scaled_z); -- /* Here an overflow is theoretically possible, in which case -- the result may be wrong, hence the assert. An underflow -- is not possible, but let's check that anyway. */ -- MPFR_ASSERTN (! MPFR_OVERFLOW (flags)); /* TODO... */ -- MPFR_ASSERTN (! MPFR_UNDERFLOW (flags)); /* not possible */ -- if (rnd_mode == MPFR_RNDN && -- MPFR_GET_EXP (s) == __gmpfr_emin - 1 + scale && -- mpfr_powerof2_raw (s)) -- { -- MPFR_LOG_MSG (("Double rounding\n", 0)); -- rnd_mode = (MPFR_IS_NEG (s) ? inexact <= 0 : inexact >= 0) -- ? MPFR_RNDZ : MPFR_RNDA; -- } -- inex2 = mpfr_div_2ui (s, s, scale, rnd_mode); -- MPFR_LOG_MSG (("inex2=%d\n", inex2)); -- if (inex2) /* underflow */ -- inexact = inex2; -- } -- } -+ MPFR_LOG_MSG (("Use UBF\n", 0)); - -- /* FIXME/TODO: I'm not sure that the following is correct. -- Check for possible spurious exceptions due to intermediate -- computations. */ -- MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags); -- goto end; -- } -+ MPFR_TMP_MARK (marker); -+ un = MPFR_LIMB_SIZE (x) + MPFR_LIMB_SIZE (y); -+ MPFR_TMP_INIT (up, uu, (mpfr_prec_t) un * GMP_NUMB_BITS, un); -+ mpfr_ubf_mul_exact (uu, x, y); -+ mpfr_clear_flags (); -+ inexact = mpfr_add (s, (mpfr_srcptr) uu, z, rnd_mode); -+ MPFR_UBF_CLEAR_EXP (uu); -+ MPFR_TMP_FREE (marker); -+ } -+ } -+ else -+ { -+ add: -+ inexact = mpfr_add (s, u, z, rnd_mode); -+ MPFR_GROUP_CLEAR (group); - } - -- inexact = mpfr_add (s, u, z, rnd_mode); -- MPFR_GROUP_CLEAR (group); - MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags); -- end: - MPFR_SAVE_EXPO_FREE (expo); - return mpfr_check_range (s, inexact, rnd_mode); - } -diff -Naurd mpfr-4.0.1-a/src/mpfr.h mpfr-4.0.1-b/src/mpfr.h ---- mpfr-4.0.1-a/src/mpfr.h 2018-04-27 12:40:46.870268475 +0000 -+++ mpfr-4.0.1-b/src/mpfr.h 2018-04-27 12:45:53.171452379 +0000 -@@ -27,7 +27,7 @@ - #define MPFR_VERSION_MAJOR 4 - #define MPFR_VERSION_MINOR 0 - #define MPFR_VERSION_PATCHLEVEL 1 --#define MPFR_VERSION_STRING "4.0.1-p1" -+#define MPFR_VERSION_STRING "4.0.1-p2" - - /* User macros: - MPFR_USE_FILE: Define it to make MPFR define functions dealing -diff -Naurd mpfr-4.0.1-a/src/version.c mpfr-4.0.1-b/src/version.c ---- mpfr-4.0.1-a/src/version.c 2018-04-27 12:40:46.870268475 +0000 -+++ mpfr-4.0.1-b/src/version.c 2018-04-27 12:45:53.171452379 +0000 -@@ -25,5 +25,5 @@ - const char * - mpfr_get_version (void) - { -- return "4.0.1-p1"; -+ return "4.0.1-p2"; - } -diff -Naurd mpfr-4.0.1-a/tests/tfma.c mpfr-4.0.1-b/tests/tfma.c ---- mpfr-4.0.1-a/tests/tfma.c 2018-01-09 12:30:58.000000000 +0000 -+++ mpfr-4.0.1-b/tests/tfma.c 2018-04-27 12:45:53.163452452 +0000 -@@ -196,6 +196,238 @@ - } - - static void -+test_overflow3 (void) -+{ -+ mpfr_t x, y, z, r; -+ int inex; -+ mpfr_prec_t p = 8; -+ mpfr_flags_t ex_flags = MPFR_FLAGS_OVERFLOW | MPFR_FLAGS_INEXACT, flags; -+ int i, j, k; -+ unsigned int neg; -+ -+ mpfr_inits2 (p, x, y, z, (mpfr_ptr) 0); -+ for (i = 0; i < 2; i++) -+ { -+ mpfr_init2 (r, 2 * p + i); -+ mpfr_set_ui_2exp (x, 1, mpfr_get_emax () - 1, MPFR_RNDN); -+ mpfr_set_ui (y, 2, MPFR_RNDN); /* y = 2 */ -+ for (j = 1; j <= 2; j++) -+ for (k = 0; k <= 1; k++) -+ { -+ mpfr_set_si_2exp (z, -1, mpfr_get_emax () - mpfr_get_prec (r) - j, -+ MPFR_RNDN); -+ if (k) -+ mpfr_nextabove (z); -+ for (neg = 0; neg <= 3; neg++) -+ { -+ mpfr_clear_flags (); -+ /* (The following applies for neg = 0 or 2, all the signs -+ need to be reversed for neg = 1 or 3.) -+ We have x*y = 2^emax and -+ z = - 2^(emax-2p-i-j) * (1-k*2^(-p)), thus -+ x*y+z = 2^emax - 2^(emax-2p-i-j) + k*2^(emax-3p-i-j) -+ should overflow. Indeed it is >= the midpoint of -+ 2^emax - 2^(emax-2p-i) and 2^emax, the midpoint -+ being obtained for j = 1 and k = 0. */ -+ inex = mpfr_fma (r, x, y, z, MPFR_RNDN); -+ flags = __gmpfr_flags; -+ if (! mpfr_inf_p (r) || flags != ex_flags || -+ ((neg & 1) == 0 ? -+ (inex <= 0 || MPFR_IS_NEG (r)) : -+ (inex >= 0 || MPFR_IS_POS (r)))) -+ { -+ printf ("Error in test_overflow3 for " -+ "i=%d j=%d k=%d neg=%u\n", i, j, k, neg); -+ printf ("Expected %c@Inf@\n with inex %c 0 and flags:", -+ (neg & 1) == 0 ? '+' : '-', -+ (neg & 1) == 0 ? '>' : '<'); -+ flags_out (ex_flags); -+ printf ("Got "); -+ mpfr_dump (r); -+ printf (" with inex = %d and flags:", inex); -+ flags_out (flags); -+ exit (1); -+ } -+ if (neg == 0 || neg == 2) -+ mpfr_neg (x, x, MPFR_RNDN); -+ if (neg == 1 || neg == 3) -+ mpfr_neg (y, y, MPFR_RNDN); -+ mpfr_neg (z, z, MPFR_RNDN); -+ } /* neg */ -+ } /* k */ -+ mpfr_clear (r); -+ } /* i */ -+ mpfr_clears (x, y, z, (mpfr_ptr) 0); -+} -+ -+static void -+test_overflow4 (void) -+{ -+ mpfr_t x, y, z, r1, r2; -+ mpfr_exp_t emax, e; -+ mpfr_prec_t px; -+ mpfr_flags_t flags1, flags2; -+ int inex1, inex2; -+ int ei, i, j; -+ int below; -+ unsigned int neg; -+ -+ emax = mpfr_get_emax (); -+ -+ mpfr_init2 (y, MPFR_PREC_MIN); -+ mpfr_set_ui (y, 2, MPFR_RNDN); /* y = 2 */ -+ -+ mpfr_init2 (z, 8); -+ -+ for (px = 17; px < 256; px *= 2) -+ { -+ mpfr_init2 (x, px); -+ mpfr_inits2 (px - 8, r1, r2, (mpfr_ptr) 0); -+ for (ei = 0; ei <= 1; ei++) -+ { -+ e = ei ? emax : 0; -+ mpfr_set_ui_2exp (x, 1, e - 1, MPFR_RNDN); -+ mpfr_nextabove (x); /* x = 2^(e - 1) + 2^(e - px) */ -+ /* x*y = 2^e + 2^(e - px + 1), which internally overflows -+ when e = emax. */ -+ for (i = -4; i <= 4; i++) -+ for (j = 2; j <= 3; j++) -+ { -+ mpfr_set_si_2exp (z, -j, e - px + i, MPFR_RNDN); -+ /* If |z| <= 2^(e - px + 1), then x*y + z >= 2^e and -+ RZ(x*y + z) = 2^e with an unbounded exponent range. -+ If |z| > 2^(e - px + 1), then RZ(x*y + z) is the -+ predecessor of 2^e (since |z| < ulp(r)/2); this -+ occurs when i > 0 and when i = 0 and j > 2 */ -+ mpfr_set_ui_2exp (r1, 1, e - 1, MPFR_RNDN); -+ below = i > 0 || (i == 0 && j > 2); -+ if (below) -+ mpfr_nextbelow (r1); -+ mpfr_clear_flags (); -+ inex1 = mpfr_mul_2ui (r1, r1, 1, MPFR_RNDZ); -+ if (below || e < emax) -+ { -+ inex1 = i == 0 && j == 2 ? 0 : -1; -+ flags1 = inex1 ? MPFR_FLAGS_INEXACT : 0; -+ } -+ else -+ { -+ MPFR_ASSERTN (inex1 < 0); -+ flags1 = MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW; -+ MPFR_ASSERTN (flags1 == __gmpfr_flags); -+ } -+ for (neg = 0; neg <= 3; neg++) -+ { -+ mpfr_clear_flags (); -+ inex2 = mpfr_fma (r2, x, y, z, MPFR_RNDZ); -+ flags2 = __gmpfr_flags; -+ if (! (mpfr_equal_p (r1, r2) && -+ SAME_SIGN (inex1, inex2) && -+ flags1 == flags2)) -+ { -+ printf ("Error in test_overflow4 for " -+ "px=%d ei=%d i=%d j=%d neg=%u\n", -+ (int) px, ei, i, j, neg); -+ printf ("Expected "); -+ mpfr_dump (r1); -+ printf ("with inex = %d and flags:", inex1); -+ flags_out (flags1); -+ printf ("Got "); -+ mpfr_dump (r2); -+ printf ("with inex = %d and flags:", inex2); -+ flags_out (flags2); -+ exit (1); -+ } -+ if (neg == 0 || neg == 2) -+ mpfr_neg (x, x, MPFR_RNDN); -+ if (neg == 1 || neg == 3) -+ mpfr_neg (y, y, MPFR_RNDN); -+ mpfr_neg (z, z, MPFR_RNDN); -+ mpfr_neg (r1, r1, MPFR_RNDN); -+ inex1 = - inex1; -+ } -+ } -+ } -+ mpfr_clears (x, r1, r2, (mpfr_ptr) 0); -+ } -+ -+ mpfr_clears (y, z, (mpfr_ptr) 0); -+} -+ -+static void -+test_overflow5 (void) -+{ -+ mpfr_t x, y, z, r1, r2; -+ mpfr_exp_t emax; -+ int inex1, inex2; -+ int i, rnd; -+ unsigned int neg, negr; -+ -+ emax = mpfr_get_emax (); -+ -+ mpfr_init2 (x, 123); -+ mpfr_init2 (y, 45); -+ mpfr_init2 (z, 67); -+ mpfr_inits2 (89, r1, r2, (mpfr_ptr) 0); -+ -+ mpfr_set_ui_2exp (x, 1, emax - 1, MPFR_RNDN); -+ -+ for (i = 3; i <= 17; i++) -+ { -+ mpfr_set_ui (y, i, MPFR_RNDN); -+ mpfr_set_ui_2exp (z, 1, emax - 1, MPFR_RNDN); -+ for (neg = 0; neg < 8; neg++) -+ { -+ mpfr_setsign (x, x, neg & 1, MPFR_RNDN); -+ mpfr_setsign (y, y, neg & 2, MPFR_RNDN); -+ mpfr_setsign (z, z, neg & 4, MPFR_RNDN); -+ -+ /* |x*y + z| = (i +/- 1) * 2^(emax - 1) >= 2^emax (overflow) -+ and x*y + z has the same sign as x*y. */ -+ negr = (neg ^ (neg >> 1)) & 1; -+ -+ RND_LOOP (rnd) -+ { -+ mpfr_set_inf (r1, 1); -+ if (MPFR_IS_LIKE_RNDZ ((mpfr_rnd_t) rnd, negr)) -+ { -+ mpfr_nextbelow (r1); -+ inex1 = -1; -+ } -+ else -+ inex1 = 1; -+ -+ if (negr) -+ { -+ mpfr_neg (r1, r1, MPFR_RNDN); -+ inex1 = - inex1; -+ } -+ -+ mpfr_clear_flags (); -+ inex2 = mpfr_fma (r2, x, y, z, (mpfr_rnd_t) rnd); -+ MPFR_ASSERTN (__gmpfr_flags == -+ (MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW)); -+ -+ if (! (mpfr_equal_p (r1, r2) && SAME_SIGN (inex1, inex2))) -+ { -+ printf ("Error in test_overflow5 for i=%d neg=%u %s\n", -+ i, neg, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); -+ printf ("Expected "); -+ mpfr_dump (r1); -+ printf ("with inex = %d\n", inex1); -+ printf ("Got "); -+ mpfr_dump (r2); -+ printf ("with inex = %d\n", inex2); -+ exit (1); -+ } -+ } /* rnd */ -+ } /* neg */ -+ } /* i */ -+ -+ mpfr_clears (x, y, z, r1, r2, (mpfr_ptr) 0); -+} -+ -+static void - test_underflow1 (void) - { - mpfr_t x, y, z, r; -@@ -281,59 +513,128 @@ - static void - test_underflow2 (void) - { -- mpfr_t x, y, z, r; -- int b, i, inex, same, err = 0; -+ mpfr_t x, y, z, r1, r2; -+ int e, b, i, prec = 32, pz, inex; -+ unsigned int neg; - -- mpfr_inits2 (32, x, y, z, r, (mpfr_ptr) 0); -+ mpfr_init2 (x, MPFR_PREC_MIN); -+ mpfr_inits2 (prec, y, z, r1, r2, (mpfr_ptr) 0); - -- mpfr_set_si_2exp (z, 1, mpfr_get_emin (), MPFR_RNDN); /* z = 2^emin */ -- mpfr_set_si_2exp (x, 1, mpfr_get_emin (), MPFR_RNDN); /* x = 2^emin */ -+ mpfr_set_si_2exp (x, 1, mpfr_get_emin () - 1, MPFR_RNDN); -+ /* x = 2^(emin-1) */ - -- for (b = 0; b <= 1; b++) -+ for (e = -1; e <= prec + 2; e++) - { -- for (i = 15; i <= 17; i++) -+ mpfr_set (z, x, MPFR_RNDN); -+ /* z = x = 2^(emin+e) */ -+ for (b = 0; b <= 1; b++) - { -- mpfr_set_si_2exp (y, i, -4 - MPFR_PREC (z), MPFR_RNDN); -- /* z = 1.000...00b -- * xy = 01111 -- * or 10000 -- * or 10001 -- */ -- mpfr_clear_flags (); -- inex = mpfr_fma (r, x, y, z, MPFR_RNDN); --#define STRTU2 "Error in test_underflow2 (b = %d, i = %d)\n " -- if (__gmpfr_flags != MPFR_FLAGS_INEXACT) -- { -- printf (STRTU2 "flags = %u instead of %u\n", b, i, -- (unsigned int) __gmpfr_flags, -- (unsigned int) MPFR_FLAGS_INEXACT); -- err = 1; -- } -- same = i == 15 || (i == 16 && b == 0); -- if (same ? (inex >= 0) : (inex <= 0)) -- { -- printf (STRTU2 "incorrect ternary value (%d instead of %c 0)\n", -- b, i, inex, same ? '<' : '>'); -- err = 1; -- } -- mpfr_set (y, z, MPFR_RNDN); -- if (!same) -- mpfr_nextabove (y); -- if (! mpfr_equal_p (r, y)) -+ for (pz = prec - 4 * (b == 0); pz <= prec + 4; pz++) - { -- printf (STRTU2 "expected ", b, i); -- mpfr_dump (y); -- printf (" got "); -- mpfr_dump (r); -- err = 1; -- } -- } -- mpfr_nextabove (z); -- } -+ inex = mpfr_prec_round (z, pz, MPFR_RNDZ); -+ MPFR_ASSERTN (inex == 0); -+ for (i = 15; i <= 17; i++) -+ { -+ mpfr_flags_t flags1, flags2; -+ int inex1, inex2; - -- if (err) -- exit (1); -- mpfr_clears (x, y, z, r, (mpfr_ptr) 0); -+ mpfr_set_si_2exp (y, i, -4 - prec, MPFR_RNDN); -+ -+ /* <--- r ---> -+ * z = 1.000...00b with b = 0 or 1 -+ * xy = 01111 (i = 15) -+ * or 10000 (i = 16) -+ * or 10001 (i = 17) -+ * -+ * x, y, and z will be modified to test the different sign -+ * combinations. In the case b = 0 (i.e. |z| is a power of -+ * 2) and x*y has a different sign from z, then y will be -+ * divided by 2, so that i = 16 corresponds to a midpoint. -+ */ -+ -+ for (neg = 0; neg < 8; neg++) -+ { -+ int xyneg, prev_binade; -+ -+ mpfr_setsign (x, x, neg & 1, MPFR_RNDN); -+ mpfr_setsign (y, y, neg & 2, MPFR_RNDN); -+ mpfr_setsign (z, z, neg & 4, MPFR_RNDN); -+ -+ xyneg = (neg ^ (neg >> 1)) & 1; /* true iff x*y < 0 */ -+ -+ /* If a change of binade occurs by adding x*y to z -+ exactly, then take into account the fact that the -+ midpoint has a different exponent. */ -+ prev_binade = b == 0 && (xyneg ^ MPFR_IS_NEG (z)); -+ if (prev_binade) -+ mpfr_div_2ui (y, y, 1, MPFR_RNDN); -+ -+ mpfr_set (r1, z, MPFR_RNDN); -+ flags1 = MPFR_FLAGS_INEXACT; -+ -+ if (e == -1 && i == 17 && b == 0 && -+ (xyneg ^ (neg >> 2)) != 0) -+ { -+ /* Special underflow case. */ -+ flags1 |= MPFR_FLAGS_UNDERFLOW; -+ inex1 = xyneg ? 1 : -1; -+ } -+ else if (i == 15 || (i == 16 && b == 0)) -+ { -+ /* round toward z */ -+ inex1 = xyneg ? 1 : -1; -+ } -+ else if (xyneg) -+ { -+ /* round away from z, with x*y < 0 */ -+ mpfr_nextbelow (r1); -+ inex1 = -1; -+ } -+ else -+ { -+ /* round away from z, with x*y > 0 */ -+ mpfr_nextabove (r1); -+ inex1 = 1; -+ } -+ -+ mpfr_clear_flags (); -+ inex2 = mpfr_fma (r2, x, y, z, MPFR_RNDN); -+ flags2 = __gmpfr_flags; -+ -+ if (! (mpfr_equal_p (r1, r2) && -+ SAME_SIGN (inex1, inex2) && -+ flags1 == flags2)) -+ { -+ printf ("Error in test_underflow2 for " -+ "e=%d b=%d pz=%d i=%d neg=%u\n", -+ e, b, pz, i, neg); -+ printf ("Expected "); -+ mpfr_dump (r1); -+ printf ("with inex = %d and flags:", inex1); -+ flags_out (flags1); -+ printf ("Got "); -+ mpfr_dump (r2); -+ printf ("with inex = %d and flags:", inex2); -+ flags_out (flags2); -+ exit (1); -+ } -+ -+ /* Restore y. */ -+ if (prev_binade) -+ mpfr_mul_2ui (y, y, 1, MPFR_RNDN); -+ } /* neg */ -+ } /* i */ -+ } /* pz */ -+ -+ inex = mpfr_prec_round (z, prec, MPFR_RNDZ); -+ MPFR_ASSERTN (inex == 0); -+ MPFR_SET_POS (z); -+ mpfr_nextabove (z); -+ } /* b */ -+ mpfr_mul_2ui (x, x, 1, MPFR_RNDN); -+ } /* e */ -+ -+ mpfr_clears (x, y, z, r1, r2, (mpfr_ptr) 0); - } - - static void -@@ -397,6 +698,185 @@ - mpfr_clears (x, y, z, t1, t2, (mpfr_ptr) 0); - } - -+/* Test s = x*y + z with PREC(z) > PREC(s) + 1, x*y underflows, where -+ z + x*y and z + sign(x*y) * 2^(emin-1) do not give the same result. -+ x = 2^emin -+ y = 2^(-8) -+ z = 2^emin * (2^PREC(s) + k - 2^(-1)) -+ with k = 3 for MPFR_RNDN and k = 2 for the directed rounding modes. -+ Also test the opposite versions with neg != 0. -+*/ -+static void -+test_underflow4 (void) -+{ -+ mpfr_t x, y, z, s1, s2; -+ mpfr_prec_t ps = 32; -+ int inex, rnd; -+ -+ mpfr_inits2 (MPFR_PREC_MIN, x, y, (mpfr_ptr) 0); -+ mpfr_inits2 (ps, s1, s2, (mpfr_ptr) 0); -+ mpfr_init2 (z, ps + 2); -+ -+ inex = mpfr_set_si_2exp (x, 1, mpfr_get_emin (), MPFR_RNDN); -+ MPFR_ASSERTN (inex == 0); -+ inex = mpfr_set_si_2exp (y, 1, -8, MPFR_RNDN); -+ MPFR_ASSERTN (inex == 0); -+ -+ RND_LOOP_NO_RNDF (rnd) -+ { -+ mpfr_flags_t flags1, flags2; -+ int inex1, inex2; -+ unsigned int neg; -+ -+ inex = mpfr_set_si_2exp (z, 1 << 1, ps, MPFR_RNDN); -+ MPFR_ASSERTN (inex == 0); -+ inex = mpfr_sub_ui (z, z, 1, MPFR_RNDN); -+ MPFR_ASSERTN (inex == 0); -+ inex = mpfr_div_2ui (z, z, 1, MPFR_RNDN); -+ MPFR_ASSERTN (inex == 0); -+ inex = mpfr_add_ui (z, z, rnd == MPFR_RNDN ? 3 : 2, MPFR_RNDN); -+ MPFR_ASSERTN (inex == 0); -+ inex = mpfr_mul (z, z, x, MPFR_RNDN); -+ MPFR_ASSERTN (inex == 0); -+ -+ for (neg = 0; neg <= 3; neg++) -+ { -+ inex1 = mpfr_set (s1, z, (mpfr_rnd_t) rnd); -+ flags1 = MPFR_FLAGS_INEXACT; -+ -+ mpfr_clear_flags (); -+ inex2 = mpfr_fma (s2, x, y, z, (mpfr_rnd_t) rnd); -+ flags2 = __gmpfr_flags; -+ -+ if (! (mpfr_equal_p (s1, s2) && -+ SAME_SIGN (inex1, inex2) && -+ flags1 == flags2)) -+ { -+ printf ("Error in test_underflow4 for neg=%u %s\n", -+ neg, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); -+ printf ("Expected "); -+ mpfr_dump (s1); -+ printf (" with inex ~ %d, flags =", inex1); -+ flags_out (flags1); -+ printf ("Got "); -+ mpfr_dump (s2); -+ printf (" with inex ~ %d, flags =", inex2); -+ flags_out (flags2); -+ exit (1); -+ } -+ -+ if (neg == 0 || neg == 2) -+ mpfr_neg (x, x, MPFR_RNDN); -+ if (neg == 1 || neg == 3) -+ mpfr_neg (y, y, MPFR_RNDN); -+ mpfr_neg (z, z, MPFR_RNDN); -+ } -+ } -+ -+ mpfr_clears (x, y, z, s1, s2, (mpfr_ptr) 0); -+} -+ -+/* Test s = x*y + z on: -+ x = +/- 2^emin -+ y = +/- 2^(-3) -+ z = +/- 2^(emin + PREC(s)) and MPFR numbers close to this value. -+ with PREC(z) from PREC(s) - 2 to PREC(s) + 8. -+*/ -+static void -+test_underflow5 (void) -+{ -+ mpfr_t w, x, y, z, s1, s2, t; -+ mpfr_exp_t emin; -+ mpfr_prec_t ps = 32; -+ int inex, i, j, rnd; -+ unsigned int neg; -+ -+ mpfr_inits2 (MPFR_PREC_MIN, w, x, y, (mpfr_ptr) 0); -+ mpfr_inits2 (ps, s1, s2, (mpfr_ptr) 0); -+ mpfr_init2 (t, ps + 9); -+ -+ emin = mpfr_get_emin (); -+ -+ inex = mpfr_set_si_2exp (w, 1, emin, MPFR_RNDN); /* w = 2^emin */ -+ MPFR_ASSERTN (inex == 0); -+ inex = mpfr_set_si (x, 1, MPFR_RNDN); -+ MPFR_ASSERTN (inex == 0); -+ inex = mpfr_set_si_2exp (y, 1, -3, MPFR_RNDN); -+ MPFR_ASSERTN (inex == 0); -+ -+ for (i = -2; i <= 8; i++) -+ { -+ mpfr_init2 (z, ps + i); -+ inex = mpfr_set_si_2exp (z, 1, ps, MPFR_RNDN); -+ MPFR_ASSERTN (inex == 0); -+ -+ for (j = 1; j <= 32; j++) -+ mpfr_nextbelow (z); -+ -+ for (j = -32; j <= 32; j++) -+ { -+ for (neg = 0; neg < 8; neg++) -+ { -+ mpfr_setsign (x, x, neg & 1, MPFR_RNDN); -+ mpfr_setsign (y, y, neg & 2, MPFR_RNDN); -+ mpfr_setsign (z, z, neg & 4, MPFR_RNDN); -+ -+ inex = mpfr_fma (t, x, y, z, MPFR_RNDN); -+ MPFR_ASSERTN (inex == 0); -+ -+ inex = mpfr_mul (x, x, w, MPFR_RNDN); -+ MPFR_ASSERTN (inex == 0); -+ inex = mpfr_mul (z, z, w, MPFR_RNDN); -+ MPFR_ASSERTN (inex == 0); -+ -+ RND_LOOP_NO_RNDF (rnd) -+ { -+ mpfr_flags_t flags1, flags2; -+ int inex1, inex2; -+ -+ mpfr_clear_flags (); -+ inex1 = mpfr_mul (s1, w, t, (mpfr_rnd_t) rnd); -+ flags1 = __gmpfr_flags; -+ -+ mpfr_clear_flags (); -+ inex2 = mpfr_fma (s2, x, y, z, (mpfr_rnd_t) rnd); -+ flags2 = __gmpfr_flags; -+ -+ if (! (mpfr_equal_p (s1, s2) && -+ SAME_SIGN (inex1, inex2) && -+ flags1 == flags2)) -+ { -+ printf ("Error in test_underflow5 on " -+ "i=%d j=%d neg=%u %s\n", i, j, neg, -+ mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); -+ printf ("Expected "); -+ mpfr_dump (s1); -+ printf (" with inex ~ %d, flags =", inex1); -+ flags_out (flags1); -+ printf ("Got "); -+ mpfr_dump (s2); -+ printf (" with inex ~ %d, flags =", inex2); -+ flags_out (flags2); -+ exit (1); -+ } -+ } /* rnd */ -+ -+ inex = mpfr_div (x, x, w, MPFR_RNDN); -+ MPFR_ASSERTN (inex == 0); -+ inex = mpfr_div (z, z, w, MPFR_RNDN); -+ MPFR_ASSERTN (inex == 0); -+ } /* neg */ -+ -+ MPFR_SET_POS (z); /* restore the value before the loop on neg */ -+ mpfr_nextabove (z); -+ } /* j */ -+ -+ mpfr_clear (z); -+ } /* i */ -+ -+ mpfr_clears (w, x, y, s1, s2, t, (mpfr_ptr) 0); -+} -+ - static void - bug20101018 (void) - { -@@ -533,6 +1013,7 @@ - { - mpfr_t x, y, z, s; - mpfr_exp_t emin, emax; -+ int i; - - tests_start_mpfr (); - -@@ -823,21 +1304,39 @@ - - test_exact (); - -- test_overflow1 (); -- test_overflow2 (); -- test_underflow1 (); -- test_underflow2 (); -- test_underflow3 (1); -+ for (i = 0; i <= 2; i++) -+ { -+ if (i == 0) -+ { -+ /* corresponds to the generic code + mpfr_check_range */ -+ set_emin (-1024); -+ set_emax (1024); -+ } -+ else if (i == 1) -+ { -+ set_emin (MPFR_EMIN_MIN); -+ set_emax (MPFR_EMAX_MAX); -+ } -+ else -+ { -+ MPFR_ASSERTN (i == 2); -+ if (emin == MPFR_EMIN_MIN && emax == MPFR_EMAX_MAX) -+ break; -+ set_emin (emin); -+ set_emax (emax); -+ } - -- set_emin (MPFR_EMIN_MIN); -- set_emax (MPFR_EMAX_MAX); -- test_overflow1 (); -- test_overflow2 (); -- test_underflow1 (); -- test_underflow2 (); -- test_underflow3 (2); -- set_emin (emin); -- set_emax (emax); -+ test_overflow1 (); -+ test_overflow2 (); -+ test_overflow3 (); -+ test_overflow4 (); -+ test_overflow5 (); -+ test_underflow1 (); -+ test_underflow2 (); -+ test_underflow3 (i); -+ test_underflow4 (); -+ test_underflow5 (); -+ } - - tests_end_mpfr (); - return 0; -diff -Naurd mpfr-4.0.1-a/PATCHES mpfr-4.0.1-b/PATCHES ---- mpfr-4.0.1-a/PATCHES 2018-04-27 12:47:54.194308761 +0000 -+++ mpfr-4.0.1-b/PATCHES 2018-04-27 12:47:54.230308407 +0000 -@@ -0,0 +1 @@ -+sqr_1n-underflow -diff -Naurd mpfr-4.0.1-a/VERSION mpfr-4.0.1-b/VERSION ---- mpfr-4.0.1-a/VERSION 2018-04-27 12:45:53.171452379 +0000 -+++ mpfr-4.0.1-b/VERSION 2018-04-27 12:47:54.226308446 +0000 -@@ -1 +1 @@ --4.0.1-p2 -+4.0.1-p3 -diff -Naurd mpfr-4.0.1-a/src/mpfr.h mpfr-4.0.1-b/src/mpfr.h ---- mpfr-4.0.1-a/src/mpfr.h 2018-04-27 12:45:53.171452379 +0000 -+++ mpfr-4.0.1-b/src/mpfr.h 2018-04-27 12:47:54.226308446 +0000 -@@ -27,7 +27,7 @@ - #define MPFR_VERSION_MAJOR 4 - #define MPFR_VERSION_MINOR 0 - #define MPFR_VERSION_PATCHLEVEL 1 --#define MPFR_VERSION_STRING "4.0.1-p2" -+#define MPFR_VERSION_STRING "4.0.1-p3" - - /* User macros: - MPFR_USE_FILE: Define it to make MPFR define functions dealing -diff -Naurd mpfr-4.0.1-a/src/sqr.c mpfr-4.0.1-b/src/sqr.c ---- mpfr-4.0.1-a/src/sqr.c 2018-01-09 12:30:58.000000000 +0000 -+++ mpfr-4.0.1-b/src/sqr.c 2018-04-27 12:47:54.218308525 +0000 -@@ -161,15 +161,18 @@ - if (MPFR_UNLIKELY(ax < __gmpfr_emin)) - { - /* As seen in mpfr_mul_1, we cannot have a0 = 111...111 here if there -- was not exponent decrease (ax--) above. -- In the case of an exponent decrease, it is not possible for -- GMP_NUMB_BITS=32 since the largest b0 such that b0^2 < 2^(2*32-1) -- is b0=3037000499, but its square has only 30 leading ones. -- For GMP_NUMB_BITS=64 it is possible: the largest b0 is -- 13043817825332782212, and its square has 64 leading ones. */ -- if ((ax == __gmpfr_emin - 1) && (ap[0] == ~MPFR_LIMB_HIGHBIT) && -- ((rnd_mode == MPFR_RNDN && rb) || -- (MPFR_IS_LIKE_RNDA(rnd_mode, MPFR_IS_NEG (a)) && (rb | sb)))) -+ was not an exponent decrease (ax--) above. -+ In the case of an exponent decrease: -+ - For GMP_NUMB_BITS=32, a0 = 111...111 is not possible since the -+ largest b0 such that b0^2 < 2^(2*32-1) is b0=3037000499, but -+ its square has only 30 leading ones. -+ - For GMP_NUMB_BITS=64, a0 = 111...111 is possible: the largest b0 -+ is 13043817825332782212, and its square has 64 leading ones; but -+ since the next bit is rb=0, for RNDN, we always have an underflow. -+ For the test below, note that a is positive. -+ */ -+ if (ax == __gmpfr_emin - 1 && ap[0] == MPFR_LIMB_MAX && -+ MPFR_IS_LIKE_RNDA (rnd_mode, 0)) - goto rounding; /* no underflow */ - /* For RNDN, mpfr_underflow always rounds away, thus for |a| <= 2^(emin-2) - we have to change to RNDZ. This corresponds to: -diff -Naurd mpfr-4.0.1-a/src/version.c mpfr-4.0.1-b/src/version.c ---- mpfr-4.0.1-a/src/version.c 2018-04-27 12:45:53.171452379 +0000 -+++ mpfr-4.0.1-b/src/version.c 2018-04-27 12:47:54.226308446 +0000 -@@ -25,5 +25,5 @@ - const char * - mpfr_get_version (void) - { -- return "4.0.1-p2"; -+ return "4.0.1-p3"; - } -diff -Naurd mpfr-4.0.1-a/tests/tsqr.c mpfr-4.0.1-b/tests/tsqr.c ---- mpfr-4.0.1-a/tests/tsqr.c 2018-01-09 12:30:58.000000000 +0000 -+++ mpfr-4.0.1-b/tests/tsqr.c 2018-04-27 12:47:54.218308525 +0000 -@@ -188,6 +188,156 @@ - #endif - } - -+static void -+coverage (mpfr_prec_t pmax) -+{ -+ mpfr_prec_t p; -+ -+ for (p = MPFR_PREC_MIN; p <= pmax; p++) -+ { -+ mpfr_t a, b, c; -+ int inex; -+ mpfr_exp_t emin; -+ -+ mpfr_init2 (a, p); -+ mpfr_init2 (b, p); -+ mpfr_init2 (c, p); -+ -+ /* exercise carry in most significant bits of a, with overflow */ -+ mpfr_set_ui_2exp (b, 1, mpfr_get_emax (), MPFR_RNDZ); -+ mpfr_sqrt (b, b, MPFR_RNDU); -+ mpfr_div_2exp (c, b, 1, MPFR_RNDN); -+ mpfr_sqr (c, c, MPFR_RNDN); -+ mpfr_clear_flags (); -+ inex = mpfr_sqr (a, b, MPFR_RNDN); -+ /* if EXP(c) > emax-2, there is overflow */ -+ if (mpfr_get_exp (c) > mpfr_get_emax () - 2) -+ { -+ MPFR_ASSERTN(inex > 0); -+ MPFR_ASSERTN(mpfr_inf_p (a) && mpfr_sgn (a) > 0); -+ MPFR_ASSERTN(mpfr_overflow_p ()); -+ } -+ else /* no overflow */ -+ { -+ /* 2^p-1 is a square only for p=1 */ -+ MPFR_ASSERTN((p == 1 && inex == 0) || (p > 1 && inex < 0)); -+ MPFR_ASSERTN(!mpfr_overflow_p ()); -+ mpfr_set_ui_2exp (c, 1, mpfr_get_emax (), MPFR_RNDZ); -+ MPFR_ASSERTN(mpfr_equal_p (a, c)); -+ } -+ -+ /* same as above, with RNDU */ -+ mpfr_set_ui_2exp (b, 1, mpfr_get_emax (), MPFR_RNDZ); -+ mpfr_sqrt (b, b, MPFR_RNDU); -+ mpfr_div_2exp (c, b, 1, MPFR_RNDN); -+ mpfr_sqr (c, c, MPFR_RNDU); -+ mpfr_clear_flags (); -+ inex = mpfr_sqr (a, b, MPFR_RNDU); -+ /* if EXP(c) > emax-2, there is overflow */ -+ if (mpfr_get_exp (c) > mpfr_get_emax () - 2) -+ { -+ MPFR_ASSERTN(inex > 0); -+ MPFR_ASSERTN(mpfr_inf_p (a) && mpfr_sgn (a) > 0); -+ MPFR_ASSERTN(mpfr_overflow_p ()); -+ } -+ else /* no overflow */ -+ { -+ /* 2^p-1 is a square only for p=1 */ -+ MPFR_ASSERTN((p == 1 && inex == 0) || (p > 1 && inex < 0)); -+ MPFR_ASSERTN(!mpfr_overflow_p ()); -+ mpfr_set_ui_2exp (c, 1, mpfr_get_emax (), MPFR_RNDZ); -+ MPFR_ASSERTN(mpfr_equal_p (a, c)); -+ } -+ -+ /* exercise trivial overflow */ -+ mpfr_set_ui_2exp (b, 1, mpfr_get_emax (), MPFR_RNDZ); -+ mpfr_sqrt (b, b, MPFR_RNDU); -+ mpfr_mul_2exp (b, b, 1, MPFR_RNDN); -+ mpfr_clear_flags (); -+ inex = mpfr_sqr (a, b, MPFR_RNDN); -+ MPFR_ASSERTN(inex > 0); -+ MPFR_ASSERTN(mpfr_inf_p (a) && mpfr_sgn (a) > 0); -+ MPFR_ASSERTN(mpfr_overflow_p ()); -+ -+ /* exercise trivial underflow */ -+ mpfr_set_ui_2exp (b, 1, mpfr_get_emin () - 1, MPFR_RNDZ); -+ mpfr_sqrt (b, b, MPFR_RNDU); -+ mpfr_div_2exp (b, b, 1, MPFR_RNDN); -+ mpfr_clear_flags (); -+ inex = mpfr_sqr (a, b, MPFR_RNDN); -+ MPFR_ASSERTN(inex < 0); -+ MPFR_ASSERTN(mpfr_zero_p (a) && mpfr_signbit (a) == 0); -+ MPFR_ASSERTN(mpfr_underflow_p ()); -+ -+ /* exercise square between 0.5*2^emin and its predecessor (emin even) */ -+ emin = mpfr_get_emin (); -+ mpfr_set_emin (emin + (emin & 1)); /* now emin is even */ -+ mpfr_set_ui_2exp (b, 1, mpfr_get_emin () - 1, MPFR_RNDN); -+ inex = mpfr_sqrt (b, b, MPFR_RNDZ); -+ MPFR_ASSERTN(inex != 0); /* sqrt(2) is not exact */ -+ mpfr_mul_2exp (c, b, 1, MPFR_RNDN); -+ mpfr_sqr (c, c, MPFR_RNDN); -+ mpfr_clear_flags (); -+ inex = mpfr_sqr (a, b, MPFR_RNDN); -+ if (mpfr_get_exp (c) < mpfr_get_emin () + 2) /* underflow */ -+ { -+ /* if c > 0.5*2^(emin+1), we should round to 0.5*2^emin */ -+ if (mpfr_cmp_ui_2exp (c, 1, mpfr_get_emin ()) > 0) -+ { -+ MPFR_ASSERTN(inex > 0); -+ MPFR_ASSERTN(mpfr_cmp_ui_2exp (a, 1, mpfr_get_emin () - 1) == 0); -+ MPFR_ASSERTN(mpfr_underflow_p ()); -+ } -+ else /* we should round to 0 */ -+ { -+ MPFR_ASSERTN(inex < 0); -+ MPFR_ASSERTN(mpfr_zero_p (a) && mpfr_signbit (a) == 0); -+ MPFR_ASSERTN(mpfr_underflow_p ()); -+ } -+ } -+ else -+ { -+ MPFR_ASSERTN(inex > 0); -+ MPFR_ASSERTN(mpfr_cmp_ui_2exp (a, 1, mpfr_get_emin () - 1) == 0); -+ MPFR_ASSERTN(!mpfr_underflow_p ()); -+ } -+ mpfr_set_emin (emin); -+ -+ /* exercise exact square root 2^(emin-2) for emin even */ -+ emin = mpfr_get_emin (); -+ mpfr_set_emin (emin + (emin & 1)); /* now emin is even */ -+ mpfr_set_ui_2exp (b, 1, (mpfr_get_emin () - 2) / 2, MPFR_RNDN); -+ inex = mpfr_sqr (a, b, MPFR_RNDN); -+ MPFR_ASSERTN(inex < 0); -+ MPFR_ASSERTN(mpfr_zero_p (a) && mpfr_signbit (a) == 0); -+ MPFR_ASSERTN(mpfr_underflow_p ()); -+ mpfr_set_emin (emin); -+ -+ /* same as above, for RNDU */ -+ emin = mpfr_get_emin (); -+ mpfr_set_emin (emin + (emin & 1)); /* now emin is even */ -+ mpfr_set_ui_2exp (b, 1, mpfr_get_emin () - 1, MPFR_RNDN); -+ inex = mpfr_sqrt (b, b, MPFR_RNDZ); -+ MPFR_ASSERTN(inex != 0); /* sqrt(2) is not exact */ -+ mpfr_mul_2exp (c, b, 1, MPFR_RNDN); -+ mpfr_sqr (c, c, MPFR_RNDU); -+ mpfr_clear_flags (); -+ inex = mpfr_sqr (a, b, MPFR_RNDU); -+ MPFR_ASSERTN(inex > 0); -+ MPFR_ASSERTN(mpfr_cmp_ui_2exp (a, 1, mpfr_get_emin () - 1) == 0); -+ /* we have underflow if c < 2^(emin+1) */ -+ if (mpfr_cmp_ui_2exp (c, 1, mpfr_get_emin () + 1) < 0) -+ MPFR_ASSERTN(mpfr_underflow_p ()); -+ else -+ MPFR_ASSERTN(!mpfr_underflow_p ()); -+ mpfr_set_emin (emin); -+ -+ mpfr_clear (a); -+ mpfr_clear (b); -+ mpfr_clear (c); -+ } -+} -+ - int - main (void) - { -@@ -195,6 +345,7 @@ - - tests_start_mpfr (); - -+ coverage (1024); - check_mpn_sqr (); - check_special (); - test_underflow (); -diff -Naurd mpfr-4.0.1-a/PATCHES mpfr-4.0.1-b/PATCHES ---- mpfr-4.0.1-a/PATCHES 2018-04-27 12:50:10.592974822 +0000 -+++ mpfr-4.0.1-b/PATCHES 2018-04-27 12:50:10.624974512 +0000 -@@ -0,0 +1 @@ -+get_str -diff -Naurd mpfr-4.0.1-a/VERSION mpfr-4.0.1-b/VERSION ---- mpfr-4.0.1-a/VERSION 2018-04-27 12:47:54.226308446 +0000 -+++ mpfr-4.0.1-b/VERSION 2018-04-27 12:50:10.624974512 +0000 -@@ -1 +1 @@ --4.0.1-p3 -+4.0.1-p4 -diff -Naurd mpfr-4.0.1-a/doc/mpfr.texi mpfr-4.0.1-b/doc/mpfr.texi ---- mpfr-4.0.1-a/doc/mpfr.texi 2018-02-07 12:50:31.000000000 +0000 -+++ mpfr-4.0.1-b/doc/mpfr.texi 2018-04-27 12:50:10.612974628 +0000 -@@ -1655,8 +1655,8 @@ - @deftypefun {char *} mpfr_get_str (char *@var{str}, mpfr_exp_t *@var{expptr}, int @var{b}, size_t @var{n}, mpfr_t @var{op}, mpfr_rnd_t @var{rnd}) - Convert @var{op} to a string of digits in base @var{b}, with rounding in - the direction @var{rnd}, where @var{n} is either zero (see below) or the --number of significant digits output in the string; in the latter case, --@var{n} must be greater or equal to 2. The base may vary from 2 to 62; -+number of significant digits output in the string. -+The base may vary from 2 to 62; - otherwise the function does nothing and immediately returns a null pointer. - - If the input is NaN, then the returned string is @samp{@@NaN@@} and the -@@ -1699,8 +1699,7 @@ - but in some very rare cases, it might be @math{m+1} - (the smallest case for bases up to 62 is when @var{p} equals 186564318007 - for bases 7 and 49). --@c In the source src/get_str.c, this is due to the approximate mpfr_ceil_mul, --@c but also m = 1 is changed to 2. -+@c In the source src/get_str.c, this is due to the approximate mpfr_ceil_mul. - - If @var{str} is a null pointer, space for the significand is allocated using - the allocation function (@pxref{Memory Handling}) and a pointer to the string -diff -Naurd mpfr-4.0.1-a/doc/mpfr.info mpfr-4.0.1-b/doc/mpfr.info ---- mpfr-4.0.1-a/doc/mpfr.info 2018-02-07 12:58:03.000000000 +0000 -+++ mpfr-4.0.1-b/doc/mpfr.info 2018-04-27 12:50:17.128911341 +0000 -@@ -1321,10 +1321,9 @@ - size_t N, mpfr_t OP, mpfr_rnd_t RND) - Convert OP to a string of digits in base B, with rounding in the - direction RND, where N is either zero (see below) or the number of -- significant digits output in the string; in the latter case, N must -- be greater or equal to 2. The base may vary from 2 to 62; -- otherwise the function does nothing and immediately returns a null -- pointer. -+ significant digits output in the string. The base may vary from 2 -+ to 62; otherwise the function does nothing and immediately returns -+ a null pointer. - - If the input is NaN, then the returned string is ‘@NaN@’ and the - NaN flag is set. If the input is +Inf (resp. −Inf), then the -@@ -4471,21 +4470,21 @@ - * mpfr_expm1: Special Functions. (line 40) - * mpfr_fac_ui: Special Functions. (line 136) - * mpfr_fits_intmax_p: Conversion Functions. -- (line 168) -+ (line 167) - * mpfr_fits_sint_p: Conversion Functions. -- (line 164) -+ (line 163) - * mpfr_fits_slong_p: Conversion Functions. -- (line 162) -+ (line 161) - * mpfr_fits_sshort_p: Conversion Functions. -- (line 166) -+ (line 165) - * mpfr_fits_uintmax_p: Conversion Functions. -- (line 167) -+ (line 166) - * mpfr_fits_uint_p: Conversion Functions. -- (line 163) -+ (line 162) - * mpfr_fits_ulong_p: Conversion Functions. -- (line 161) -+ (line 160) - * mpfr_fits_ushort_p: Conversion Functions. -- (line 165) -+ (line 164) - * mpfr_flags_clear: Exception Related Functions. - (line 190) - * mpfr_flags_restore: Exception Related Functions. -@@ -4520,7 +4519,7 @@ - * mpfr_free_cache2: Special Functions. (line 295) - * mpfr_free_pool: Special Functions. (line 309) - * mpfr_free_str: Conversion Functions. -- (line 156) -+ (line 155) - * mpfr_frexp: Conversion Functions. - (line 49) - * mpfr_gamma: Special Functions. (line 155) -@@ -4928,30 +4927,30 @@ - Node: Assignment Functions47553 - Node: Combined Initialization and Assignment Functions57499 - Node: Conversion Functions58800 --Node: Basic Arithmetic Functions69381 --Node: Comparison Functions80277 --Node: Special Functions83765 --Node: Input and Output Functions101974 --Node: Formatted Output Functions106751 --Node: Integer and Remainder Related Functions116956 --Node: Rounding-Related Functions124484 --Node: Miscellaneous Functions131001 --Node: Exception Related Functions141493 --Node: Compatibility with MPF151733 --Node: Custom Interface154679 --Node: Internals159310 --Node: API Compatibility160854 --Node: Type and Macro Changes162802 --Node: Added Functions165985 --Node: Changed Functions170499 --Node: Removed Functions177095 --Node: Other Changes177825 --Node: MPFR and the IEEE 754 Standard179526 --Node: Contributors182143 --Node: References185200 --Node: GNU Free Documentation License187084 --Node: Concept Index209677 --Node: Function and Type Index216049 -+Node: Basic Arithmetic Functions69323 -+Node: Comparison Functions80219 -+Node: Special Functions83707 -+Node: Input and Output Functions101916 -+Node: Formatted Output Functions106693 -+Node: Integer and Remainder Related Functions116898 -+Node: Rounding-Related Functions124426 -+Node: Miscellaneous Functions130943 -+Node: Exception Related Functions141435 -+Node: Compatibility with MPF151675 -+Node: Custom Interface154621 -+Node: Internals159252 -+Node: API Compatibility160796 -+Node: Type and Macro Changes162744 -+Node: Added Functions165927 -+Node: Changed Functions170441 -+Node: Removed Functions177037 -+Node: Other Changes177767 -+Node: MPFR and the IEEE 754 Standard179468 -+Node: Contributors182085 -+Node: References185142 -+Node: GNU Free Documentation License187026 -+Node: Concept Index209619 -+Node: Function and Type Index215991 -  - End Tag Table - -diff -Naurd mpfr-4.0.1-a/src/get_str.c mpfr-4.0.1-b/src/get_str.c ---- mpfr-4.0.1-a/src/get_str.c 2018-01-09 12:30:58.000000000 +0000 -+++ mpfr-4.0.1-b/src/get_str.c 2018-04-27 12:50:10.612974628 +0000 -@@ -2325,15 +2325,12 @@ - */ - m = 1 + - mpfr_ceil_mul (IS_POW2(b) ? MPFR_PREC(x) - 1 : MPFR_PREC(x), b, 1); -- if (m < 2) -- m = 2; - } - - MPFR_LOG_MSG (("m=%zu\n", m)); - -- /* The code below for non-power-of-two bases works for m=1; -- this is important for the internal use of mpfr_get_str. */ -- MPFR_ASSERTN (m >= 2 || (!IS_POW2(b) && m >= 1)); -+ /* The code below works for m=1, both for power-of-two and non-power-of-two -+ bases; this is important for the internal use of mpfr_get_str. */ - - /* x is a floating-point number */ - -@@ -2376,6 +2373,8 @@ - - /* the first digit will contain only r bits */ - prec = (m - 1) * pow2 + r; /* total number of bits */ -+ /* if m=1 then 1 <= prec <= pow2, and since prec=1 is now valid in MPFR, -+ the power-of-two code also works for m=1 */ - n = MPFR_PREC2LIMBS (prec); - - MPFR_TMP_MARK (marker); -diff -Naurd mpfr-4.0.1-a/src/mpfr.h mpfr-4.0.1-b/src/mpfr.h ---- mpfr-4.0.1-a/src/mpfr.h 2018-04-27 12:47:54.226308446 +0000 -+++ mpfr-4.0.1-b/src/mpfr.h 2018-04-27 12:50:10.620974551 +0000 -@@ -27,7 +27,7 @@ - #define MPFR_VERSION_MAJOR 4 - #define MPFR_VERSION_MINOR 0 - #define MPFR_VERSION_PATCHLEVEL 1 --#define MPFR_VERSION_STRING "4.0.1-p3" -+#define MPFR_VERSION_STRING "4.0.1-p4" - - /* User macros: - MPFR_USE_FILE: Define it to make MPFR define functions dealing -diff -Naurd mpfr-4.0.1-a/src/version.c mpfr-4.0.1-b/src/version.c ---- mpfr-4.0.1-a/src/version.c 2018-04-27 12:47:54.226308446 +0000 -+++ mpfr-4.0.1-b/src/version.c 2018-04-27 12:50:10.624974512 +0000 -@@ -25,5 +25,5 @@ - const char * - mpfr_get_version (void) - { -- return "4.0.1-p3"; -+ return "4.0.1-p4"; - } -diff -Naurd mpfr-4.0.1-a/tests/tget_str.c mpfr-4.0.1-b/tests/tget_str.c ---- mpfr-4.0.1-a/tests/tget_str.c 2018-01-09 12:30:58.000000000 +0000 -+++ mpfr-4.0.1-b/tests/tget_str.c 2018-04-27 12:50:10.612974628 +0000 -@@ -1267,6 +1267,41 @@ - - #define ITER 1000 - -+static void -+coverage (void) -+{ -+ mpfr_t x; -+ char s[42]; -+ mpfr_exp_t e; -+ int b = 3; -+ size_t m = 40; -+ -+ mpfr_init2 (x, 128); -+ -+ /* exercise corner case in mpfr_get_str_aux: exact case (e < 0), where r -+ rounds to a power of 2, and f is a multiple of GMP_NUMB_BITS */ -+ mpfr_set_ui_2exp (x, 1, 64, MPFR_RNDU); -+ mpfr_nextbelow (x); -+ /* x = 2^64 - 2^(-64) */ -+ mpfr_get_str (s, &e, b, m, x, MPFR_RNDU); -+ /* s is the base-3 string for 6148914691236517206 (in base 10) */ -+ MPFR_ASSERTN(strcmp (s, "1111222002212212010121102012021021021200") == 0); -+ MPFR_ASSERTN(e == 41); -+ -+ /* exercise corner case in mpfr_get_str: input is m=0, then it is changed -+ to m=1 */ -+ mpfr_set_prec (x, 1); -+ mpfr_set_ui (x, 1, MPFR_RNDN); -+ mpfr_get_str (s, &e, 2, 0, x, MPFR_RNDN); -+ MPFR_ASSERTN(strcmp (s, "1") == 0); -+ MPFR_ASSERTN(e == 1); -+ mpfr_get_str (s, &e, 2, 1, x, MPFR_RNDN); -+ MPFR_ASSERTN(strcmp (s, "1") == 0); -+ MPFR_ASSERTN(e == 1); -+ -+ mpfr_clear (x); -+} -+ - int - main (int argc, char *argv[]) - { -@@ -1281,6 +1316,7 @@ - - tests_start_mpfr (); - -+ coverage (); - check_small (); - - check_special (2, 2); -diff -Naurd mpfr-4.0.1-a/PATCHES mpfr-4.0.1-b/PATCHES ---- mpfr-4.0.1-a/PATCHES 2018-04-27 12:52:13.875783093 +0000 -+++ mpfr-4.0.1-b/PATCHES 2018-04-27 12:52:13.911782747 +0000 -@@ -0,0 +1 @@ -+cmp_q-special -diff -Naurd mpfr-4.0.1-a/VERSION mpfr-4.0.1-b/VERSION ---- mpfr-4.0.1-a/VERSION 2018-04-27 12:50:10.624974512 +0000 -+++ mpfr-4.0.1-b/VERSION 2018-04-27 12:52:13.911782747 +0000 -@@ -1 +1 @@ --4.0.1-p4 -+4.0.1-p5 -diff -Naurd mpfr-4.0.1-a/src/gmp_op.c mpfr-4.0.1-b/src/gmp_op.c ---- mpfr-4.0.1-a/src/gmp_op.c 2018-01-09 12:30:58.000000000 +0000 -+++ mpfr-4.0.1-b/src/gmp_op.c 2018-04-27 12:52:13.899782862 +0000 -@@ -452,11 +452,15 @@ - mpfr_prec_t p; - MPFR_SAVE_EXPO_DECL (expo); - -- if (MPFR_UNLIKELY (mpq_denref (q) == 0)) -+ if (MPFR_UNLIKELY (mpz_sgn (mpq_denref (q)) == 0)) - { - /* q is an infinity or NaN */ -- mpfr_init2 (t, 2); -+ mpfr_flags_t old_flags; -+ -+ mpfr_init2 (t, MPFR_PREC_MIN); -+ old_flags = __gmpfr_flags; - mpfr_set_q (t, q, MPFR_RNDN); -+ __gmpfr_flags = old_flags; - res = mpfr_cmp (x, t); - mpfr_clear (t); - return res; -diff -Naurd mpfr-4.0.1-a/src/mpfr.h mpfr-4.0.1-b/src/mpfr.h ---- mpfr-4.0.1-a/src/mpfr.h 2018-04-27 12:50:10.620974551 +0000 -+++ mpfr-4.0.1-b/src/mpfr.h 2018-04-27 12:52:13.907782785 +0000 -@@ -27,7 +27,7 @@ - #define MPFR_VERSION_MAJOR 4 - #define MPFR_VERSION_MINOR 0 - #define MPFR_VERSION_PATCHLEVEL 1 --#define MPFR_VERSION_STRING "4.0.1-p4" -+#define MPFR_VERSION_STRING "4.0.1-p5" - - /* User macros: - MPFR_USE_FILE: Define it to make MPFR define functions dealing -diff -Naurd mpfr-4.0.1-a/src/version.c mpfr-4.0.1-b/src/version.c ---- mpfr-4.0.1-a/src/version.c 2018-04-27 12:50:10.624974512 +0000 -+++ mpfr-4.0.1-b/src/version.c 2018-04-27 12:52:13.911782747 +0000 -@@ -25,5 +25,5 @@ - const char * - mpfr_get_version (void) - { -- return "4.0.1-p4"; -+ return "4.0.1-p5"; - } -diff -Naurd mpfr-4.0.1-a/tests/tgmpop.c mpfr-4.0.1-b/tests/tgmpop.c ---- mpfr-4.0.1-a/tests/tgmpop.c 2018-01-09 12:30:58.000000000 +0000 -+++ mpfr-4.0.1-b/tests/tgmpop.c 2018-04-27 12:52:13.899782862 +0000 -@@ -307,16 +307,39 @@ - mpfr_init2 (z, MPFR_PREC_MIN); - mpq_init (y); - -- /* check the erange flag when x is NaN */ -+ /* Check the flags when x is NaN: the erange flags must be set, and -+ only this one. */ - mpfr_set_nan (x); - mpq_set_ui (y, 17, 1); -- mpfr_clear_erangeflag (); -+ mpfr_clear_flags (); - res1 = mpfr_cmp_q (x, y); -- if (res1 != 0 || mpfr_erangeflag_p () == 0) -+ if (res1 != 0 || __gmpfr_flags != MPFR_FLAGS_ERANGE) - { - printf ("Error for mpfr_cmp_q (NaN, 17)\n"); - printf ("Return value: expected 0, got %d\n", res1); -- printf ("Erange flag: expected set, got %d\n", mpfr_erangeflag_p ()); -+ printf ("Expected flags:"); -+ flags_out (MPFR_FLAGS_ERANGE); -+ printf ("Got flags: "); -+ flags_out (__gmpfr_flags); -+ exit (1); -+ } -+ -+ /* Check the flags when y is NaN: the erange flags must be set, and -+ only this one. */ -+ mpfr_set_ui (x, 42, MPFR_RNDN); -+ /* A NaN rational is represented by 0/0 (MPFR extension). */ -+ mpz_set_ui (mpq_numref (y), 0); -+ mpz_set_ui (mpq_denref (y), 0); -+ mpfr_clear_flags (); -+ res1 = mpfr_cmp_q (x, y); -+ if (res1 != 0 || __gmpfr_flags != MPFR_FLAGS_ERANGE) -+ { -+ printf ("Error for mpfr_cmp_q (42, NaN)\n"); -+ printf ("Return value: expected 0, got %d\n", res1); -+ printf ("Expected flags:"); -+ flags_out (MPFR_FLAGS_ERANGE); -+ printf ("Got flags: "); -+ flags_out (__gmpfr_flags); - exit (1); - } - -@@ -341,6 +364,55 @@ - } - } - } -+ -+ /* check for y = 1/0 */ -+ mpz_set_ui (mpq_numref (y), 1); -+ mpz_set_ui (mpq_denref (y), 0); -+ mpfr_set_ui (x, 1, MPFR_RNDN); -+ MPFR_ASSERTN(mpfr_cmp_q (x, y) < 0); -+ mpfr_set_inf (x, -1); -+ MPFR_ASSERTN(mpfr_cmp_q (x, y) < 0); -+ mpfr_set_inf (x, +1); -+ MPFR_ASSERTN(mpfr_cmp_q (x, y) == 0); -+ mpfr_set_nan (x); -+ mpfr_clear_erangeflag (); -+ MPFR_ASSERTN(mpfr_cmp_q (x, y) == 0); -+ MPFR_ASSERTN(mpfr_erangeflag_p ()); -+ -+ /* check for y = -1/0 */ -+ mpz_set_si (mpq_numref (y), -1); -+ mpz_set_ui (mpq_denref (y), 0); -+ mpfr_set_ui (x, 1, MPFR_RNDN); -+ MPFR_ASSERTN(mpfr_cmp_q (x, y) > 0); -+ mpfr_set_inf (x, -1); -+ MPFR_ASSERTN(mpfr_cmp_q (x, y) == 0); -+ mpfr_set_inf (x, +1); -+ MPFR_ASSERTN(mpfr_cmp_q (x, y) > 0); -+ mpfr_set_nan (x); -+ mpfr_clear_erangeflag (); -+ MPFR_ASSERTN(mpfr_cmp_q (x, y) == 0); -+ MPFR_ASSERTN(mpfr_erangeflag_p ()); -+ -+ /* check for y = 0/0 */ -+ mpz_set_ui (mpq_numref (y), 0); -+ mpz_set_ui (mpq_denref (y), 0); -+ mpfr_set_ui (x, 1, MPFR_RNDN); -+ mpfr_clear_erangeflag (); -+ MPFR_ASSERTN(mpfr_cmp_q (x, y) == 0); -+ MPFR_ASSERTN(mpfr_erangeflag_p ()); -+ mpfr_set_inf (x, -1); -+ mpfr_clear_erangeflag (); -+ MPFR_ASSERTN(mpfr_cmp_q (x, y) == 0); -+ MPFR_ASSERTN(mpfr_erangeflag_p ()); -+ mpfr_set_inf (x, +1); -+ mpfr_clear_erangeflag (); -+ MPFR_ASSERTN(mpfr_cmp_q (x, y) == 0); -+ MPFR_ASSERTN(mpfr_erangeflag_p ()); -+ mpfr_set_nan (x); -+ mpfr_clear_erangeflag (); -+ MPFR_ASSERTN(mpfr_cmp_q (x, y) == 0); -+ MPFR_ASSERTN(mpfr_erangeflag_p ()); -+ - mpq_clear (y); - mpfr_clear (x); - mpfr_clear (z); -diff -Naurd mpfr-4.0.1-a/PATCHES mpfr-4.0.1-b/PATCHES ---- mpfr-4.0.1-a/PATCHES 2018-04-27 12:54:17.862594948 +0000 -+++ mpfr-4.0.1-b/PATCHES 2018-04-27 12:54:17.894594642 +0000 -@@ -0,0 +1 @@ -+io-null-stream -diff -Naurd mpfr-4.0.1-a/VERSION mpfr-4.0.1-b/VERSION ---- mpfr-4.0.1-a/VERSION 2018-04-27 12:52:13.911782747 +0000 -+++ mpfr-4.0.1-b/VERSION 2018-04-27 12:54:17.894594642 +0000 -@@ -1 +1 @@ --4.0.1-p5 -+4.0.1-p6 -diff -Naurd mpfr-4.0.1-a/src/inp_str.c mpfr-4.0.1-b/src/inp_str.c ---- mpfr-4.0.1-a/src/inp_str.c 2018-01-09 12:30:58.000000000 +0000 -+++ mpfr-4.0.1-b/src/inp_str.c 2018-04-27 12:54:17.882594757 +0000 -@@ -37,9 +37,6 @@ - int retval; - size_t nread; - -- if (stream == NULL) -- stream = stdin; -- - alloc_size = 100; - str = (unsigned char *) mpfr_allocate_func (alloc_size); - str_size = 0; -diff -Naurd mpfr-4.0.1-a/src/mpfr.h mpfr-4.0.1-b/src/mpfr.h ---- mpfr-4.0.1-a/src/mpfr.h 2018-04-27 12:52:13.907782785 +0000 -+++ mpfr-4.0.1-b/src/mpfr.h 2018-04-27 12:54:17.894594642 +0000 -@@ -27,7 +27,7 @@ - #define MPFR_VERSION_MAJOR 4 - #define MPFR_VERSION_MINOR 0 - #define MPFR_VERSION_PATCHLEVEL 1 --#define MPFR_VERSION_STRING "4.0.1-p5" -+#define MPFR_VERSION_STRING "4.0.1-p6" - - /* User macros: - MPFR_USE_FILE: Define it to make MPFR define functions dealing -diff -Naurd mpfr-4.0.1-a/src/out_str.c mpfr-4.0.1-b/src/out_str.c ---- mpfr-4.0.1-a/src/out_str.c 2018-01-09 12:30:58.000000000 +0000 -+++ mpfr-4.0.1-b/src/out_str.c 2018-04-27 12:54:17.882594757 +0000 -@@ -43,10 +43,6 @@ - - MPFR_ASSERTN (base >= 2 && base <= 62); - -- /* when stream=NULL, output to stdout */ -- if (stream == NULL) -- stream = stdout; -- - if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (op))) - { - if (MPFR_IS_NAN (op)) -diff -Naurd mpfr-4.0.1-a/src/version.c mpfr-4.0.1-b/src/version.c ---- mpfr-4.0.1-a/src/version.c 2018-04-27 12:52:13.911782747 +0000 -+++ mpfr-4.0.1-b/src/version.c 2018-04-27 12:54:17.894594642 +0000 -@@ -25,5 +25,5 @@ - const char * - mpfr_get_version (void) - { -- return "4.0.1-p5"; -+ return "4.0.1-p6"; - } diff --git a/mpfr-4.0.1.tar.bz2 b/mpfr-4.0.1.tar.bz2 deleted file mode 100644 index cf6de14..0000000 --- a/mpfr-4.0.1.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a4d97610ba8579d380b384b225187c250ef88cfe1d5e7226b89519374209b86b -size 1626420 diff --git a/mpfr-4.0.1.tar.bz2.asc b/mpfr-4.0.1.tar.bz2.asc deleted file mode 100644 index 617bb6a..0000000 --- a/mpfr-4.0.1.tar.bz2.asc +++ /dev/null @@ -1,6 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iF0EABECAB0WIQQH89u+zBo5YFB4CU2YDBl2mMNznQUCWnr4PgAKCRCYDBl2mMNz -nbAUAJ400b+qoWF9e4rUt9zxAax+/wOVwgCeJEBEIQAl3kLf6ylQ93BiQhh/ivM= -=b5mY ------END PGP SIGNATURE----- diff --git a/mpfr-4.0.2.tar.bz2 b/mpfr-4.0.2.tar.bz2 new file mode 100644 index 0000000..f9c37d5 --- /dev/null +++ b/mpfr-4.0.2.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c05e3f02d09e0e9019384cdd58e0f19c64e6db1fd6f5ecf77b4b1c61ca253acc +size 1652074 diff --git a/mpfr-4.0.2.tar.bz2.asc b/mpfr-4.0.2.tar.bz2.asc new file mode 100644 index 0000000..12c7be1 --- /dev/null +++ b/mpfr-4.0.2.tar.bz2.asc @@ -0,0 +1,6 @@ +-----BEGIN PGP SIGNATURE----- + +iF0EABECAB0WIQQH89u+zBo5YFB4CU2YDBl2mMNznQUCXFNeRQAKCRCYDBl2mMNz +nZChAJ9pmLqxHt7JMLrx1p1bsX+AfzPSVwCeJktDkGbMsZh9fW5wjfvGri1zh4w= +=oULh +-----END PGP SIGNATURE----- diff --git a/mpfr.changes b/mpfr.changes index c19b918..2439749 100644 --- a/mpfr.changes +++ b/mpfr.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Feb 1 08:32:04 UTC 2019 - rguenther@suse.com + +- Update to mpfr 4.0.2 + * Cummulative bugfix release, includes mpfr-4.0.1-cummulative-patch.patch. + ------------------------------------------------------------------- Thu May 17 06:37:28 UTC 2018 - antoine.belvire@opensuse.org diff --git a/mpfr.spec b/mpfr.spec index 2f32908..0951822 100644 --- a/mpfr.spec +++ b/mpfr.spec @@ -1,7 +1,7 @@ # # spec file for package mpfr # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: mpfr -Version: 4.0.1 +Version: 4.0.2 Release: 0 Summary: The GNU multiple-precision floating-point library License: LGPL-3.0+ @@ -27,7 +27,6 @@ Source0: http://www.mpfr.org/mpfr-%{version}/mpfr-%{version}.tar.bz2 Source1: http://www.mpfr.org/mpfr-%{version}/mpfr-%{version}.tar.bz2.asc Source2: %{name}.keyring Source3: baselibs.conf -Patch: mpfr-4.0.1-cummulative-patch.patch BuildRequires: gmp-devel BuildRequires: pkgconfig @@ -68,7 +67,6 @@ based on the GMP multiple-precision library. %prep %setup -q -%patch -p1 %build %configure \