diff options
-rw-r--r-- | src/set_ld.c | 14 | ||||
-rw-r--r-- | tests/tset_ld.c | 26 |
2 files changed, 38 insertions, 2 deletions
diff --git a/src/set_ld.c b/src/set_ld.c index f5593c238..070a1a619 100644 --- a/src/set_ld.c +++ b/src/set_ld.c @@ -102,21 +102,25 @@ mpfr_set_ld (mpfr_ptr r, long double d, mpfr_rnd_t rnd_mode) { x /= div13; /* exact */ shift_exp += 8192; + mpfr_div_2si (t, t, 8192, MPFR_RNDZ); } if (ABS (x) >= div12) { x /= div12; /* exact */ shift_exp += 4096; + mpfr_div_2si (t, t, 4096, MPFR_RNDZ); } if (ABS (x) >= div11) { x /= div11; /* exact */ shift_exp += 2048; + mpfr_div_2si (t, t, 2048, MPFR_RNDZ); } if (ABS (x) >= div10) { x /= div10; /* exact */ shift_exp += 1024; + mpfr_div_2si (t, t, 1024, MPFR_RNDZ); } /* warning: we may have DBL_MAX=2^1024*(1-2^(-53)) < x < 2^1024, therefore we have one extra exponent reduction step */ @@ -124,9 +128,10 @@ mpfr_set_ld (mpfr_ptr r, long double d, mpfr_rnd_t rnd_mode) { x /= div9; /* exact */ shift_exp += 512; + mpfr_div_2si (t, t, 512, MPFR_RNDZ); } } /* Check overflow of double */ - else + else /* no overflow on double */ { long double div9, div10, div11; @@ -149,29 +154,34 @@ mpfr_set_ld (mpfr_ptr r, long double d, mpfr_rnd_t rnd_mode) { x /= div13; /* exact */ shift_exp -= 8192; + mpfr_mul_2si (t, t, 8192, MPFR_RNDZ); } if (ABS (x) <= div12) { x /= div12; /* exact */ shift_exp -= 4096; + mpfr_mul_2si (t, t, 4096, MPFR_RNDZ); } if (ABS (x) <= div11) { x /= div11; /* exact */ shift_exp -= 2048; + mpfr_mul_2si (t, t, 2048, MPFR_RNDZ); } if (ABS (x) <= div10) { x /= div10; /* exact */ shift_exp -= 1024; + mpfr_mul_2si (t, t, 1024, MPFR_RNDZ); } if (ABS(x) <= div9) { x /= div9; /* exact */ shift_exp -= 512; + mpfr_mul_2si (t, t, 512, MPFR_RNDZ); } } - else + else /* no underflow */ { inexact = mpfr_set_d (u, (double) x, MPFR_RNDZ); MPFR_ASSERTD (inexact == 0); diff --git a/tests/tset_ld.c b/tests/tset_ld.c index 6ed4f9960..43984f61f 100644 --- a/tests/tset_ld.c +++ b/tests/tset_ld.c @@ -147,12 +147,38 @@ static void test_fixed_bugs (void) { mpfr_t x; + long double l, m; /* bug found by Steve Kargl (2009-03-14) */ mpfr_init2 (x, 64); mpfr_set_ui_2exp (x, 1, -16447, MPFR_RNDN); mpfr_get_ld (x, MPFR_RNDN); /* an assertion failed in init2.c:50 */ + /* bug reported by Jakub Jelinek (2010-10-17) + https://gforge.inria.fr/tracker/?func=detail&aid=11300 */ + mpfr_set_prec (x, MPFR_LDBL_MANT_DIG); + l = 0x1.23456789abcdef0123456789abcdp-914L; + mpfr_set_ld (x, l, MPFR_RNDN); + m = mpfr_get_ld (x, MPFR_RNDN); + if (m != l) + { + printf ("Error in get_ld o set_ld for l=%Le\n", l); + printf ("Got m=%Le instead of l\n", m); + exit (1); + } + + /* another similar test which failed with extended double precision and the + generic code for mpfr_set_ld */ + l = 0x1.23456789abcdef0123456789abcdp-968L; + mpfr_set_ld (x, l, MPFR_RNDN); + m = mpfr_get_ld (x, MPFR_RNDN); + if (m != l) + { + printf ("Error in get_ld o set_ld for l=%Le\n", l); + printf ("Got m=%Le instead of l\n", m); + exit (1); + } + mpfr_clear (x); } |