summaryrefslogtreecommitdiff
path: root/patches/mpfr/3.1.3/240-rem1.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/mpfr/3.1.3/240-rem1.patch')
-rw-r--r--patches/mpfr/3.1.3/240-rem1.patch337
1 files changed, 337 insertions, 0 deletions
diff --git a/patches/mpfr/3.1.3/240-rem1.patch b/patches/mpfr/3.1.3/240-rem1.patch
new file mode 100644
index 0000000..9d5e3c1
--- /dev/null
+++ b/patches/mpfr/3.1.3/240-rem1.patch
@@ -0,0 +1,337 @@
+diff -Naurd mpfr-3.1.3-a/PATCHES mpfr-3.1.3-b/PATCHES
+--- mpfr-3.1.3-a/PATCHES 2016-02-23 07:54:06.617533218 +0000
++++ mpfr-3.1.3-b/PATCHES 2016-02-23 07:54:06.641532898 +0000
+@@ -0,0 +1 @@
++rem1
+diff -Naurd mpfr-3.1.3-a/VERSION mpfr-3.1.3-b/VERSION
+--- mpfr-3.1.3-a/VERSION 2016-02-23 07:43:23.726095285 +0000
++++ mpfr-3.1.3-b/VERSION 2016-02-23 07:54:06.641532898 +0000
+@@ -1 +1 @@
+-3.1.3-p13
++3.1.3-p14
+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 2016-02-23 07:43:23.726095285 +0000
++++ mpfr-3.1.3-b/src/mpfr.h 2016-02-23 07:54:06.641532898 +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-p13"
++#define MPFR_VERSION_STRING "3.1.3-p14"
+
+ /* 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/rem1.c mpfr-3.1.3-b/src/rem1.c
+--- mpfr-3.1.3-a/src/rem1.c 2015-06-19 19:55:10.000000000 +0000
++++ mpfr-3.1.3-b/src/rem1.c 2016-02-23 07:54:06.633533004 +0000
+@@ -59,6 +59,7 @@
+ mpfr_exp_t ex, ey;
+ int compare, inex, q_is_odd, sign, signx = MPFR_SIGN (x);
+ mpz_t mx, my, r;
++ int tiny = 0;
+
+ MPFR_ASSERTD (rnd_q == MPFR_RNDN || rnd_q == MPFR_RNDZ);
+
+@@ -109,13 +110,27 @@
+ if (ex <= ey)
+ {
+ /* q = x/y = mx/(my*2^(ey-ex)) */
+- mpz_mul_2exp (my, my, ey - ex); /* divide mx by my*2^(ey-ex) */
+- if (rnd_q == MPFR_RNDZ)
+- /* 0 <= |r| <= |my|, r has the same sign as mx */
+- mpz_tdiv_qr (mx, r, mx, my);
++
++ /* First detect cases where q=0, to avoid creating a huge number
++ my*2^(ey-ex): if sx = mpz_sizeinbase (mx, 2) and sy =
++ mpz_sizeinbase (my, 2), we have x < 2^(ex + sx) and
++ y >= 2^(ey + sy - 1), thus if ex + sx <= ey + sy - 1
++ the quotient is 0 */
++ if (ex + (mpfr_exp_t) mpz_sizeinbase (mx, 2) <
++ ey + (mpfr_exp_t) mpz_sizeinbase (my, 2))
++ {
++ tiny = 1;
++ mpz_set (r, mx);
++ mpz_set_ui (mx, 0);
++ }
+ else
+- /* 0 <= |r| <= |my|, r has the same sign as my */
+- mpz_fdiv_qr (mx, r, mx, my);
++ {
++ mpz_mul_2exp (my, my, ey - ex); /* divide mx by my*2^(ey-ex) */
++
++ /* since mx > 0 and my > 0, we can use mpz_tdiv_qr in all cases */
++ mpz_tdiv_qr (mx, r, mx, my);
++ /* 0 <= |r| <= |my|, r has the same sign as mx */
++ }
+
+ if (rnd_q == MPFR_RNDN)
+ q_is_odd = mpz_tstbit (mx, 0);
+@@ -181,7 +196,20 @@
+ /* FIXME: the comparison 2*r < my could be done more efficiently
+ at the mpn level */
+ mpz_mul_2exp (r, r, 1);
+- compare = mpz_cmpabs (r, my);
++ /* if tiny=1, we should compare r with my*2^(ey-ex) */
++ if (tiny)
++ {
++ if (ex + (mpfr_exp_t) mpz_sizeinbase (r, 2) <
++ ey + (mpfr_exp_t) mpz_sizeinbase (my, 2))
++ compare = 0; /* r*2^ex < my*2^ey */
++ else
++ {
++ mpz_mul_2exp (my, my, ey - ex);
++ compare = mpz_cmpabs (r, my);
++ }
++ }
++ else
++ compare = mpz_cmpabs (r, my);
+ mpz_fdiv_q_2exp (r, r, 1);
+ compare = ((compare > 0) ||
+ ((rnd_q == MPFR_RNDN) && (compare == 0) && q_is_odd));
+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 2016-02-23 07:43:23.726095285 +0000
++++ mpfr-3.1.3-b/src/version.c 2016-02-23 07:54:06.641532898 +0000
+@@ -25,5 +25,5 @@
+ const char *
+ mpfr_get_version (void)
+ {
+- return "3.1.3-p13";
++ return "3.1.3-p14";
+ }
+diff -Naurd mpfr-3.1.3-a/tests/tfmod.c mpfr-3.1.3-b/tests/tfmod.c
+--- mpfr-3.1.3-a/tests/tfmod.c 2015-06-19 19:55:10.000000000 +0000
++++ mpfr-3.1.3-b/tests/tfmod.c 2016-02-23 07:54:06.633533004 +0000
+@@ -137,89 +137,90 @@
+ special (void)
+ {
+ int inexact;
+- mpfr_t x, y, r, nan;
+- mpfr_inits (x, y, r, nan, (mpfr_ptr) 0);
++ mpfr_t x, y, r, t;
+
+- mpfr_set_nan (nan);
++ mpfr_inits (x, y, r, t, (mpfr_ptr) 0);
++
++ mpfr_set_nan (t);
+
+ /* fmod (NaN, NaN) is NaN */
+ mpfr_set_nan (x);
+ mpfr_set_nan (y);
+ inexact = mpfr_fmod (r, x, y, MPFR_RNDN);
+ if (!mpfr_nan_p (r) || inexact != 0)
+- test_failed (r, nan, 0, inexact, x, y, MPFR_RNDN);
++ test_failed (r, t, 0, inexact, x, y, MPFR_RNDN);
+
+ /* fmod (NaN, +0) is NaN */
+ mpfr_set_ui (y, 0, MPFR_RNDN);
+ inexact = mpfr_fmod (r, x, y, MPFR_RNDN);
+ if (!mpfr_nan_p (r) || inexact != 0)
+- test_failed (r, nan, 0, inexact, x, y, MPFR_RNDN);
++ test_failed (r, t, 0, inexact, x, y, MPFR_RNDN);
+
+ /* fmod (+1, 0) is NaN */
+ mpfr_set_ui (x, 1, MPFR_RNDN);
+ inexact = mpfr_fmod (r, x, y, MPFR_RNDN);
+ if (!mpfr_nan_p (r) || inexact != 0)
+- test_failed (r, nan, 0, inexact, x, y, MPFR_RNDN);
++ test_failed (r, t, 0, inexact, x, y, MPFR_RNDN);
+
+ /* fmod (0, 0) is NaN */
+ mpfr_set_ui (x, 0, MPFR_RNDN);
+ inexact = mpfr_fmod (r, x, y, MPFR_RNDN);
+ if (!mpfr_nan_p (r) || inexact != 0)
+- test_failed (r, nan, 0, inexact, x, y, MPFR_RNDN);
++ test_failed (r, t, 0, inexact, x, y, MPFR_RNDN);
+
+ /* fmod (+inf, +0) is NaN */
+ mpfr_set_inf (x, +1);
+ inexact = mpfr_fmod (r, x, y, MPFR_RNDN);
+ if (!mpfr_nan_p (r) || inexact != 0)
+- test_failed (r, nan, 0, inexact, x, y, MPFR_RNDN);
++ test_failed (r, t, 0, inexact, x, y, MPFR_RNDN);
+
+ /* fmod (-inf, +0) is NaN */
+ mpfr_set_inf (x, -1);
+ inexact = mpfr_fmod (r, x, y, MPFR_RNDN);
+ if (!mpfr_nan_p (r) || inexact != 0)
+- test_failed (r, nan, 0, inexact, x, y, MPFR_RNDN);
++ test_failed (r, t, 0, inexact, x, y, MPFR_RNDN);
+
+ /* fmod (-inf, -0) is NaN */
+ mpfr_neg (x, x, MPFR_RNDN);
+ inexact = mpfr_fmod (r, x, y, MPFR_RNDN);
+ if (!mpfr_nan_p (r) || inexact != 0)
+- test_failed (r, nan, 0, inexact, x, y, MPFR_RNDN);
++ test_failed (r, t, 0, inexact, x, y, MPFR_RNDN);
+
+ /* fmod (-inf, +1) is NaN */
+ mpfr_set_ui (y, +1, MPFR_RNDN);
+ inexact = mpfr_fmod (r, x, y, MPFR_RNDN);
+ if (!mpfr_nan_p (r) || inexact != 0)
+- test_failed (r, nan, 0, inexact, x, y, MPFR_RNDN);
++ test_failed (r, t, 0, inexact, x, y, MPFR_RNDN);
+
+ /* fmod (+inf, +1) is NaN */
+ mpfr_neg (x, x, MPFR_RNDN);
+ inexact = mpfr_fmod (r, x, y, MPFR_RNDN);
+ if (!mpfr_nan_p (r) || inexact != 0)
+- test_failed (r, nan, 0, inexact, x, y, MPFR_RNDN);
++ test_failed (r, t, 0, inexact, x, y, MPFR_RNDN);
+
+ /* fmod (+inf, -inf) is NaN */
+ mpfr_set_inf (y, -1);
+ inexact = mpfr_fmod (r, x, y, MPFR_RNDN);
+ if (!mpfr_nan_p (r) || inexact != 0)
+- test_failed (r, nan, 0, inexact, x, y, MPFR_RNDN);
++ test_failed (r, t, 0, inexact, x, y, MPFR_RNDN);
+
+ /* fmod (-inf, -inf) is NaN */
+ mpfr_neg (x, x, MPFR_RNDN);
+ inexact = mpfr_fmod (r, x, y, MPFR_RNDN);
+ if (!mpfr_nan_p (r) || inexact != 0)
+- test_failed (r, nan, 0, inexact, x, y, MPFR_RNDN);
++ test_failed (r, t, 0, inexact, x, y, MPFR_RNDN);
+
+ /* fmod (-inf, +inf) is NaN */
+ mpfr_neg (y, y, MPFR_RNDN);
+ inexact = mpfr_fmod (r, x, y, MPFR_RNDN);
+ if (!mpfr_nan_p (r) || inexact != 0)
+- test_failed (r, nan, 0, inexact, x, y, MPFR_RNDN);
++ test_failed (r, t, 0, inexact, x, y, MPFR_RNDN);
+
+ /* fmod (+inf, +inf) is NaN */
+ mpfr_neg (x, x, MPFR_RNDN);
+ inexact = mpfr_fmod (r, x, y, MPFR_RNDN);
+ if (!mpfr_nan_p (r) || inexact != 0)
+- test_failed (r, nan, 0, inexact, x, y, MPFR_RNDN);
++ test_failed (r, t, 0, inexact, x, y, MPFR_RNDN);
+
+ /* fmod (x, +inf) = x, if x is finite */
+ mpfr_set_ui (x, 1, MPFR_RNDN);
+@@ -271,13 +272,13 @@
+ mpfr_set_ui (y, 0, MPFR_RNDN);
+ inexact = mpfr_fmod (r, x, y, MPFR_RNDN);
+ if (!mpfr_nan_p (r) || inexact != 0)
+- test_failed (r, nan, 0, inexact, x, y, MPFR_RNDN);
++ test_failed (r, t, 0, inexact, x, y, MPFR_RNDN);
+
+ /* fmod (+0, -0) is NaN */
+ mpfr_neg (y, y, MPFR_RNDN);
+ inexact = mpfr_fmod (r, x, y, MPFR_RNDN);
+ if (!mpfr_nan_p (r) || inexact != 0)
+- test_failed (r, nan, 0, inexact, x, y, MPFR_RNDN);
++ test_failed (r, t, 0, inexact, x, y, MPFR_RNDN);
+
+ /* fmod (+0, +1) = +0 */
+ mpfr_set_ui (y, 1, MPFR_RNDN);
+@@ -303,7 +304,18 @@
+ if (!mpfr_equal_p (r, x) || inexact != 0)
+ test_failed (r, x, 0, inexact, x, y, MPFR_RNDN);
+
+- mpfr_clears (x, y, r, nan, (mpfr_ptr) 0);
++ mpfr_set_prec (x, 380);
++ mpfr_set_prec (y, 385);
++ mpfr_set_str_binary (x, "0.11011010010110011101011000100100101100101011010001011100110001100101111001010100001011111110111100101110101010110011010101000100000100011101101100001011101110100111101111111010001001000010000110010110011100111000001110111010000100101001010111100100010001101001110100011110010000000001110001111001101100111011001000110110011100100011111110010100011001000001001011010111010000000000E0");
++ mpfr_set_str_binary (y, "0.1100011000011101011010001100010111001110110111001101010010111100111100011010010011011101111101111001010111111110001001100001111101001000000010100101111001001110010110000111001000101010111001001000100101011111000010100110001111000110011011010101111101100110010101011010011101100001011101001000101111110110110110000001001101110111110110111110111111001001011110001110011111100000000000000E-1");
++ mpfr_set_prec (r, 2);
++ inexact = mpfr_fmod (r, x, y, MPFR_RNDA);
++ mpfr_set_prec (t, 2);
++ mpfr_set_ui_2exp (t, 3, -5, MPFR_RNDN);
++ if (mpfr_cmp_ui_2exp (r, 3, -5) || inexact <= 0)
++ test_failed (r, t, 1, inexact, x, y, MPFR_RNDA);
++
++ mpfr_clears (x, y, r, t, (mpfr_ptr) 0);
+ return;
+ }
+
+@@ -313,6 +325,7 @@
+ {
+ mpfr_t x, y, r;
+ int inexact;
++
+ mpfr_inits2 (100, x, y, r, (mpfr_ptr) 0);
+
+ mpfr_set_prec (x, 3);
+@@ -353,7 +366,46 @@
+ mpfr_sin (y, y, MPFR_RNDN);
+ check (r, x, y, MPFR_RNDN);
+
+- mpfr_clears(r, x, y, (mpfr_ptr) 0);
++ mpfr_clears (x, y, r, (mpfr_ptr) 0);
++}
++
++static void
++bug20160217 (void)
++{
++ mpfr_t x, y, r;
++ int inexact, i;
++ mpfr_exp_t emin, emax;
++
++ mpfr_inits2 (53, x, y, r, (mpfr_ptr) 0);
++
++ emin = mpfr_get_emin ();
++ emax = mpfr_get_emax ();
++
++ for (i = 0; i <= 1; i++)
++ {
++ mpfr_set_zero (x, 1);
++ mpfr_nextabove (x);
++ mpfr_set_inf (y, 1);
++ mpfr_nextbelow (y);
++ inexact = mpfr_fmod (r, x, y, MPFR_RNDN);
++ if (!mpfr_equal_p (r, x) || inexact != 0)
++ {
++ printf ("Error for mpfr_fmod (r, nextabove(0), nextbelow(+inf),"
++ " MPFR_RNDN)%s\n", i ? "extended exponent range" : "");
++ printf ("Expected inex = 0, r = ");
++ mpfr_dump (x);
++ printf ("Got inex = %d, r = ", inexact);
++ mpfr_dump (r);
++ exit (1);
++ }
++ set_emin (MPFR_EMIN_MIN);
++ set_emax (MPFR_EMAX_MAX);
++ }
++
++ set_emin (emin);
++ set_emax (emax);
++
++ mpfr_clears (x, y, r, (mpfr_ptr) 0);
+ }
+
+ int
+@@ -362,6 +414,7 @@
+ tests_start_mpfr ();
+
+ bug20090519 ();
++ bug20160217 ();
+
+ test_generic (2, 100, 100);
+
+diff -Naurd mpfr-3.1.3-a/tests/tremquo.c mpfr-3.1.3-b/tests/tremquo.c
+--- mpfr-3.1.3-a/tests/tremquo.c 2015-06-19 19:55:10.000000000 +0000
++++ mpfr-3.1.3-b/tests/tremquo.c 2016-02-23 07:54:06.633533004 +0000
+@@ -59,6 +59,7 @@
+ {
+ mpfr_t x, y, r;
+ long q[1];
++ int inex;
+
+ if (argc == 3) /* usage: tremquo x y (rnd=MPFR_RNDN implicit) */
+ {
+@@ -281,6 +282,15 @@
+ MPFR_ASSERTN (mpfr_zero_p (r) && MPFR_SIGN (r) > 0);
+ MPFR_ASSERTN (q[0] == 0);
+
++ mpfr_set_prec (x, 380);
++ mpfr_set_prec (y, 385);
++ mpfr_set_str_binary (x, "0.11011010010110011101011000100100101100101011010001011100110001100101111001010100001011111110111100101110101010110011010101000100000100011101101100001011101110100111101111111010001001000010000110010110011100111000001110111010000100101001010111100100010001101001110100011110010000000001110001111001101100111011001000110110011100100011111110010100011001000001001011010111010000000000E-2");
++ mpfr_set_str_binary (y, "0.1100011000011101011010001100010111001110110111001101010010111100111100011010010011011101111101111001010111111110001001100001111101001000000010100101111001001110010110000111001000101010111001001000100101011111000010100110001111000110011011010101111101100110010101011010011101100001011101001000101111110110110110000001001101110111110110111110111111001001011110001110011111100000000000000E-1");
++ mpfr_set_prec (r, 2);
++ inex = mpfr_remainder (r, x, y, MPFR_RNDA);
++ MPFR_ASSERTN(mpfr_cmp_si_2exp (r, -3, -4) == 0);
++ MPFR_ASSERTN(inex < 0);
++
+ mpfr_clear (x);
+ mpfr_clear (y);
+ mpfr_clear (r);