1975 lines
69 KiB
Diff
1975 lines
69 KiB
Diff
|
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";
|
|||
|
}
|