| diff -Naurd mpfr-3.1.3-a/PATCHES mpfr-3.1.3-b/PATCHES |
| --- mpfr-3.1.3-a/PATCHES 2015-07-17 08:58:21.094987384 +0000 |
| +++ mpfr-3.1.3-b/PATCHES 2015-07-17 08:58:21.118986898 +0000 |
| @@ -0,0 +1 @@ |
| +frexp |
| diff -Naurd mpfr-3.1.3-a/VERSION mpfr-3.1.3-b/VERSION |
| --- mpfr-3.1.3-a/VERSION 2015-07-17 08:54:48.616811495 +0000 |
| +++ mpfr-3.1.3-b/VERSION 2015-07-17 08:58:21.118986898 +0000 |
| @@ -1 +1 @@ |
| -3.1.3-p3 |
| +3.1.3-p4 |
| diff -Naurd mpfr-3.1.3-a/src/frexp.c mpfr-3.1.3-b/src/frexp.c |
| --- mpfr-3.1.3-a/src/frexp.c 2015-06-19 19:55:09.000000000 +0000 |
| +++ mpfr-3.1.3-b/src/frexp.c 2015-07-17 08:58:21.106987142 +0000 |
| @@ -26,6 +26,13 @@ |
| mpfr_frexp (mpfr_exp_t *exp, mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd) |
| { |
| int inex; |
| + unsigned int saved_flags = __gmpfr_flags; |
| + MPFR_BLOCK_DECL (flags); |
| + |
| + MPFR_LOG_FUNC |
| + (("x[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, rnd), |
| + ("y[%Pu]=%.*Rg exp=%" MPFR_EXP_FSPEC "d inex=%d", mpfr_get_prec (y), |
| + mpfr_log_prec, y, (mpfr_eexp_t) *exp, inex)); |
| |
| if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(x))) |
| { |
| @@ -49,8 +56,32 @@ |
| } |
| } |
| |
| - inex = mpfr_set (y, x, rnd); |
| + MPFR_BLOCK (flags, inex = mpfr_set (y, x, rnd)); |
| + __gmpfr_flags = saved_flags; |
| + |
| + /* Possible overflow due to the rounding, no possible underflow. */ |
| + |
| + if (MPFR_UNLIKELY (MPFR_OVERFLOW (flags))) |
| + { |
| + int inex2; |
| + |
| + /* An overflow here means that the exponent of y would be larger than |
| + the one of x, thus x would be rounded to the next power of 2, and |
| + the returned y should be 1/2 in absolute value, rounded (i.e. with |
| + possible underflow or overflow). This also implies that x and y are |
| + different objects, so that the exponent of x has not been lost. */ |
| + MPFR_LOG_MSG (("Internal overflow\n", 0)); |
| + MPFR_ASSERTD (x != y); |
| + *exp = MPFR_GET_EXP (x) + 1; |
| + inex2 = mpfr_set_si_2exp (y, MPFR_INT_SIGN (x), -1, rnd); |
| + MPFR_LOG_MSG (("inex=%d inex2=%d\n", inex, inex2)); |
| + if (inex2 != 0) |
| + inex = inex2; |
| + MPFR_RET (inex); |
| + } |
| + |
| *exp = MPFR_GET_EXP (y); |
| - MPFR_SET_EXP (y, 0); |
| + /* Do not use MPFR_SET_EXP because the range has not been checked yet. */ |
| + MPFR_EXP (y) = 0; |
| return mpfr_check_range (y, inex, rnd); |
| } |
| 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:54:48.616811495 +0000 |
| +++ mpfr-3.1.3-b/src/mpfr.h 2015-07-17 08:58:21.114986979 +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-p3" |
| +#define MPFR_VERSION_STRING "3.1.3-p4" |
| |
| /* 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/version.c mpfr-3.1.3-b/src/version.c |
| --- mpfr-3.1.3-a/src/version.c 2015-07-17 08:54:48.616811495 +0000 |
| +++ mpfr-3.1.3-b/src/version.c 2015-07-17 08:58:21.118986898 +0000 |
| @@ -25,5 +25,5 @@ |
| const char * |
| mpfr_get_version (void) |
| { |
| - return "3.1.3-p3"; |
| + return "3.1.3-p4"; |
| } |
| diff -Naurd mpfr-3.1.3-a/tests/tfrexp.c mpfr-3.1.3-b/tests/tfrexp.c |
| --- mpfr-3.1.3-a/tests/tfrexp.c 2015-06-19 19:55:10.000000000 +0000 |
| +++ mpfr-3.1.3-b/tests/tfrexp.c 2015-07-17 08:58:21.106987142 +0000 |
| @@ -129,12 +129,115 @@ |
| mpfr_clear (x); |
| } |
| |
| +static void check1 (void) |
| +{ |
| + mpfr_exp_t emin, emax, e; |
| + mpfr_t x, y1, y2; |
| + int r, neg, red; |
| + |
| + emin = mpfr_get_emin (); |
| + emax = mpfr_get_emax (); |
| + set_emin (MPFR_EMIN_MIN); |
| + set_emax (MPFR_EMAX_MAX); |
| + |
| + mpfr_init2 (x, 7); |
| + mpfr_inits2 (4, y1, y2, (mpfr_ptr) 0); |
| + |
| + mpfr_set_ui_2exp (x, 1, -2, MPFR_RNDN); |
| + while (mpfr_regular_p (x)) |
| + { |
| + /* Test the exponents up to 3 and with the maximum exponent |
| + (to check potential intermediate overflow). */ |
| + if (MPFR_GET_EXP (x) == 4) |
| + mpfr_set_exp (x, MPFR_EMAX_MAX); |
| + e = MPFR_GET_EXP (x); |
| + for (neg = 0; neg < 2; neg++) |
| + { |
| + RND_LOOP (r) |
| + { |
| + int inex1, inex2; |
| + mpfr_exp_t e1, e2; |
| + unsigned int flags1, flags2; |
| + |
| + for (red = 0; red < 2; red++) |
| + { |
| + if (red) |
| + { |
| + /* e1: exponent of the rounded value of x. */ |
| + MPFR_ASSERTN (e1 == e || e1 == e + 1); |
| + set_emin (e); |
| + set_emax (e); |
| + mpfr_clear_flags (); |
| + inex1 = e1 < 0 ? |
| + mpfr_mul_2ui (y1, x, -e1, (mpfr_rnd_t) r) : |
| + mpfr_div_2ui (y1, x, e1, (mpfr_rnd_t) r); |
| + flags1 = __gmpfr_flags; |
| + } |
| + else |
| + { |
| + inex1 = mpfr_set (y1, x, (mpfr_rnd_t) r); |
| + e1 = MPFR_IS_INF (y1) ? e + 1 : MPFR_GET_EXP (y1); |
| + flags1 = inex1 != 0 ? MPFR_FLAGS_INEXACT : 0; |
| + } |
| + mpfr_clear_flags (); |
| + inex2 = mpfr_frexp (&e2, y2, x, (mpfr_rnd_t) r); |
| + flags2 = __gmpfr_flags; |
| + set_emin (MPFR_EMIN_MIN); |
| + set_emax (MPFR_EMAX_MAX); |
| + if ((!red || e == 0) && |
| + (! mpfr_regular_p (y2) || MPFR_GET_EXP (y2) != 0)) |
| + { |
| + printf ("Error in check1 for %s, red = %d, x = ", |
| + mpfr_print_rnd_mode ((mpfr_rnd_t) r), red); |
| + mpfr_dump (x); |
| + printf ("Expected 1/2 <= |y| < 1, got y = "); |
| + mpfr_dump (y2); |
| + exit (1); |
| + } |
| + if (!red) |
| + { |
| + if (e2 > 0) |
| + mpfr_mul_2ui (y2, y2, e2, MPFR_RNDN); |
| + else if (e2 < 0) |
| + mpfr_div_2ui (y2, y2, -e2, MPFR_RNDN); |
| + } |
| + if (! (SAME_SIGN (inex1, inex2) && |
| + mpfr_equal_p (y1, y2) && |
| + flags1 == flags2)) |
| + { |
| + printf ("Error in check1 for %s, red = %d, x = ", |
| + mpfr_print_rnd_mode ((mpfr_rnd_t) r), red); |
| + mpfr_dump (x); |
| + printf ("Expected y1 = "); |
| + mpfr_dump (y1); |
| + printf ("Got y2 = "); |
| + mpfr_dump (y2); |
| + printf ("Expected inex ~= %d, got %d\n", inex1, inex2); |
| + printf ("Expected flags:"); |
| + flags_out (flags1); |
| + printf ("Got flags: "); |
| + flags_out (flags2); |
| + exit (1); |
| + } |
| + } |
| + } |
| + mpfr_neg (x, x, MPFR_RNDN); |
| + } |
| + mpfr_nextabove (x); |
| + } |
| + |
| + mpfr_clears (x, y1, y2, (mpfr_ptr) 0); |
| + set_emin (emin); |
| + set_emax (emax); |
| +} |
| + |
| int |
| main (int argc, char *argv[]) |
| { |
| tests_start_mpfr (); |
| |
| check_special (); |
| + check1 (); |
| |
| tests_end_mpfr (); |
| return 0; |