summaryrefslogtreecommitdiff
path: root/patches/mpfr/3.1.3/150-divhigh-basecase.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/mpfr/3.1.3/150-divhigh-basecase.patch')
-rw-r--r--patches/mpfr/3.1.3/150-divhigh-basecase.patch131
1 files changed, 131 insertions, 0 deletions
diff --git a/patches/mpfr/3.1.3/150-divhigh-basecase.patch b/patches/mpfr/3.1.3/150-divhigh-basecase.patch
new file mode 100644
index 0000000..ef8d891
--- /dev/null
+++ b/patches/mpfr/3.1.3/150-divhigh-basecase.patch
@@ -0,0 +1,131 @@
+diff -Naurd mpfr-3.1.3-a/PATCHES mpfr-3.1.3-b/PATCHES
+--- mpfr-3.1.3-a/PATCHES 2015-10-29 13:47:46.735901185 +0000
++++ mpfr-3.1.3-b/PATCHES 2015-10-29 13:47:46.763900609 +0000
+@@ -0,0 +1 @@
++divhigh-basecase
+diff -Naurd mpfr-3.1.3-a/VERSION mpfr-3.1.3-b/VERSION
+--- mpfr-3.1.3-a/VERSION 2015-07-17 08:58:21.118986898 +0000
++++ mpfr-3.1.3-b/VERSION 2015-10-29 13:47:46.763900609 +0000
+@@ -1 +1 @@
+-3.1.3-p4
++3.1.3-p5
+diff -Naurd mpfr-3.1.3-a/src/mpfr.h mpfr-3.1.3-b/src/mpfr.h
+--- mpfr-3.1.3-a/src/mpfr.h 2015-07-17 08:58:21.114986979 +0000
++++ mpfr-3.1.3-b/src/mpfr.h 2015-10-29 13:47:46.759900692 +0000
+@@ -27,7 +27,7 @@
+ #define MPFR_VERSION_MAJOR 3
+ #define MPFR_VERSION_MINOR 1
+ #define MPFR_VERSION_PATCHLEVEL 3
+-#define MPFR_VERSION_STRING "3.1.3-p4"
++#define MPFR_VERSION_STRING "3.1.3-p5"
+
+ /* Macros dealing with MPFR VERSION */
+ #define MPFR_VERSION_NUM(a,b,c) (((a) << 16L) | ((b) << 8) | (c))
+diff -Naurd mpfr-3.1.3-a/src/mulders.c mpfr-3.1.3-b/src/mulders.c
+--- mpfr-3.1.3-a/src/mulders.c 2015-06-19 19:55:10.000000000 +0000
++++ mpfr-3.1.3-b/src/mulders.c 2015-10-29 13:47:46.751900855 +0000
+@@ -236,9 +236,10 @@
+ that in addition to the limb np[n-1] to reduce, we have at least 2
+ extra limbs, thus accessing np[n-3] is valid. */
+
+- /* warning: we can have np[n-1]=d1 and np[n-2]=d0, but since {np,n} < D,
+- the largest possible partial quotient is B-1 */
+- if (MPFR_UNLIKELY(np[n - 1] == d1 && np[n - 2] == d0))
++ /* Warning: we can have np[n-1]>d1 or (np[n-1]=d1 and np[n-2]>=d0) here,
++ since we truncate the divisor at each step, but since {np,n} < D
++ originally, the largest possible partial quotient is B-1. */
++ if (MPFR_UNLIKELY(np[n-1] > d1 || (np[n-1] == d1 && np[n-2] >= d0)))
+ q2 = ~ (mp_limb_t) 0;
+ else
+ udiv_qr_3by2 (q2, q1, q0, np[n - 1], np[n - 2], np[n - 3],
+diff -Naurd mpfr-3.1.3-a/src/version.c mpfr-3.1.3-b/src/version.c
+--- mpfr-3.1.3-a/src/version.c 2015-07-17 08:58:21.118986898 +0000
++++ mpfr-3.1.3-b/src/version.c 2015-10-29 13:47:46.763900609 +0000
+@@ -25,5 +25,5 @@
+ const char *
+ mpfr_get_version (void)
+ {
+- return "3.1.3-p4";
++ return "3.1.3-p5";
+ }
+diff -Naurd mpfr-3.1.3-a/tests/tdiv.c mpfr-3.1.3-b/tests/tdiv.c
+--- mpfr-3.1.3-a/tests/tdiv.c 2015-06-19 19:55:10.000000000 +0000
++++ mpfr-3.1.3-b/tests/tdiv.c 2015-10-29 13:47:46.751900855 +0000
+@@ -1099,6 +1099,69 @@
+ mpfr_set_emax (old_emax);
+ }
+
++/* Bug in mpfr_divhigh_n_basecase when all limbs of q (except the most
++ significant one) are B-1 where B=2^GMP_NUMB_BITS. Since we truncate
++ the divisor at each step, it might happen at some point that
++ (np[n-1],np[n-2]) > (d1,d0), and not only the equality.
++ Reported by Ricky Farr
++ <https://sympa.inria.fr/sympa/arc/mpfr/2015-10/msg00023.html>
++ To get a failure, a MPFR_DIVHIGH_TAB entry below the MPFR_DIV_THRESHOLD
++ limit must have a value 0. With most mparam.h files, this cannot occur. */
++static void
++test_20151023 (void)
++{
++ mpfr_prec_t p;
++ mpfr_t n, d, q, q0;
++ int inex, i;
++
++ for (p = GMP_NUMB_BITS; p <= 2000; p++)
++ {
++ mpfr_init2 (n, 2*p);
++ mpfr_init2 (d, p);
++ mpfr_init2 (q, p);
++ mpfr_init2 (q0, GMP_NUMB_BITS);
++
++ /* generate a random divisor of p bits */
++ mpfr_urandomb (d, RANDS);
++ /* generate a random quotient of GMP_NUMB_BITS bits */
++ mpfr_urandomb (q0, RANDS);
++ /* zero-pad the quotient to p bits */
++ inex = mpfr_prec_round (q0, p, MPFR_RNDN);
++ MPFR_ASSERTN(inex == 0);
++
++ for (i = 0; i < 3; i++)
++ {
++ /* i=0: try with the original quotient xxx000...000
++ i=1: try with the original quotient minus one ulp
++ i=2: try with the original quotient plus one ulp */
++ if (i == 1)
++ mpfr_nextbelow (q0);
++ else if (i == 2)
++ {
++ mpfr_nextabove (q0);
++ mpfr_nextabove (q0);
++ }
++
++ inex = mpfr_mul (n, d, q0, MPFR_RNDN);
++ MPFR_ASSERTN(inex == 0);
++ mpfr_nextabove (n);
++ mpfr_div (q, n, d, MPFR_RNDN);
++ MPFR_ASSERTN(mpfr_cmp (q, q0) == 0);
++
++ inex = mpfr_mul (n, d, q0, MPFR_RNDN);
++ MPFR_ASSERTN(inex == 0);
++ mpfr_nextbelow (n);
++ mpfr_div (q, n, d, MPFR_RNDN);
++ MPFR_ASSERTN(mpfr_cmp (q, q0) == 0);
++ }
++
++ mpfr_clear (n);
++ mpfr_clear (d);
++ mpfr_clear (q);
++ mpfr_clear (q0);
++ }
++}
++
+ #define TEST_FUNCTION test_div
+ #define TWO_ARGS
+ #define RAND_FUNCTION(x) mpfr_random2(x, MPFR_LIMB_SIZE (x), randlimb () % 100, RANDS)
+@@ -1219,6 +1282,7 @@
+ consistency ();
+ test_20070603 ();
+ test_20070628 ();
++ test_20151023 ();
+ test_generic (2, 800, 50);
+ test_extreme ();
+