summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2016-09-08 09:53:52 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2016-09-08 09:53:52 +0000
commit6972652dc142005f20bc899d1f220ea5b00263bb (patch)
tree0b67a50c897bf7099e70ca5e8787285e8dc72af7
parent96734d31a78b46b4204dbb82e0b160d1ae109844 (diff)
downloadmpfr-6972652dc142005f20bc899d1f220ea5b00263bb.tar.gz
[src/get_ld.c] Fixed bug for little-endian x86 extended precision.
[tests/tset_ld.c] Added test case. (merged changesets r10807-10809,10811-10812 from the trunk) git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/3.1@10815 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r--src/get_ld.c3
-rw-r--r--tests/tset_ld.c58
2 files changed, 59 insertions, 2 deletions
diff --git a/src/get_ld.c b/src/get_ld.c
index 1c1efedbc..3abacefb0 100644
--- a/src/get_ld.c
+++ b/src/get_ld.c
@@ -108,7 +108,6 @@ mpfr_get_ld (mpfr_srcptr x, mpfr_rnd_t rnd_mode)
}
#else
-
long double
mpfr_get_ld (mpfr_srcptr x, mpfr_rnd_t rnd_mode)
{
@@ -122,7 +121,7 @@ mpfr_get_ld (mpfr_srcptr x, mpfr_rnd_t rnd_mode)
mpfr_init2 (tmp, MPFR_LDBL_MANT_DIG);
inex = mpfr_set (tmp, x, rnd_mode);
- mpfr_set_emin (-16382-63);
+ mpfr_set_emin (-16381-63); /* emin=-16444, see below */
mpfr_set_emax (16384);
mpfr_subnormalize (tmp, mpfr_check_range (tmp, inex, rnd_mode), rnd_mode);
mpfr_prec_round (tmp, 64, MPFR_RNDZ); /* exact */
diff --git a/tests/tset_ld.c b/tests/tset_ld.c
index 6e2b931f5..46791052d 100644
--- a/tests/tset_ld.c
+++ b/tests/tset_ld.c
@@ -193,6 +193,62 @@ test_fixed_bugs (void)
mpfr_clear (x);
}
+/* bug reported by Walter Mascarenhas
+ https://sympa.inria.fr/sympa/arc/mpfr/2016-09/msg00005.html */
+static void
+bug_20160907 (void)
+{
+#if HAVE_LDOUBLE_IEEE_EXT_LITTLE
+ long double dn = 1.0, ld;
+ mpfr_t mp;
+ mpfr_exp_t e = 0;
+
+ while (dn * (long double) 0.5 != 0)
+ {
+ dn = dn * (long double) 0.5;
+ e --;
+ }
+ /* dn=2^e is now the smallest subnormal */
+
+ mpfr_init2 (mp, 64);
+ mpfr_set_ui_2exp (mp, 1, e - 1, MPFR_RNDN);
+ ld = mpfr_get_ld (mp, MPFR_RNDU);
+ /* since mp = 2^(e-1) and ld is rounded upwards, we should have
+ ld = 2^e */
+ if (ld != dn)
+ {
+ printf ("Error, ld = %Le <> dn = %Le\n", ld, dn);
+ printf ("mp=");
+ mpfr_out_str (stdout, 10, 0, mp, MPFR_RNDN);
+ printf ("\n");
+ exit (1);
+ }
+
+ /* check a few more numbers */
+ for (e = -16446; e <= -16381; e++)
+ {
+ mpfr_set_ui_2exp (mp, 1, e, MPFR_RNDN);
+ ld = mpfr_get_ld (mp, MPFR_RNDU);
+ mpfr_set_ld (mp, ld, MPFR_RNDU);
+ /* mp is 2^e rounded up, thus should be >= 2^e */
+ MPFR_ASSERTN(mpfr_cmp_ui_2exp (mp, 1, e) >= 0);
+
+ mpfr_set_ui_2exp (mp, 1, e, MPFR_RNDN);
+ ld = mpfr_get_ld (mp, MPFR_RNDD);
+ mpfr_set_ld (mp, ld, MPFR_RNDD);
+ /* mp is 2^e rounded down, thus should be <= 2^e */
+ if (mpfr_cmp_ui_2exp (mp, 3, e) > 0)
+ {
+ printf ("Error, expected value <= 2^%ld\n", e);
+ printf ("got "); mpfr_dump (mp);
+ exit (1);
+ }
+ }
+
+ mpfr_clear (mp);
+#endif
+}
+
int
main (int argc, char *argv[])
{
@@ -309,6 +365,8 @@ main (int argc, char *argv[])
test_small ();
+ bug_20160907 ();
+
tests_end_mpfr ();
return 0;