summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/set_ld.c14
-rw-r--r--tests/tset_ld.c26
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);
}