summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2008-10-29 14:29:45 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2008-10-29 14:29:45 +0000
commit620e7056072a2557366cb06a8f2603fa2642f927 (patch)
tree300aa718c70e52101c4a5be010e804bbf6dd8d8f
parent20bfb20c6799e39ad989c894fb5b3e6570170cbc (diff)
downloadmpfr-620e7056072a2557366cb06a8f2603fa2642f927.tar.gz
Fixed bug 6604 "incorrect directed rounding in mpfr_strtofr"
in strtofr.c (to be checked) and added testcases. Other minor corrections. [merged -r5655:5658 -r5659:5662 from trunk] git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/2.3@5664 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r--strtofr.c15
-rw-r--r--tests/tset_str.c19
-rw-r--r--tests/tstrtofr.c71
3 files changed, 79 insertions, 26 deletions
diff --git a/strtofr.c b/strtofr.c
index 6e5abc1ee..9f22e10c2 100644
--- a/strtofr.c
+++ b/strtofr.c
@@ -473,7 +473,7 @@ parsed_string_to_mpfr (mpfr_t x, struct parsed_string *pstr, mp_rnd_t rnd)
if (pstr_size >= pstr->prec)
pstr_size = pstr->prec;
- MPFR_ASSERTD ((mp_exp_t) pstr_size == (mp_exp_t) pstr_size);
+ MPFR_ASSERTD (pstr_size == (mp_exp_t) pstr_size);
/* convert str into binary */
real_ysize = mpn_set_str (y, pstr->mant, pstr_size, pstr->base);
@@ -656,6 +656,19 @@ parsed_string_to_mpfr (mpfr_t x, struct parsed_string *pstr, mp_rnd_t rnd)
err = 0;
}
+ if (pstr_size < pstr->prec && exact
+ && ((rnd == GMP_RNDN)
+ || ((rnd == GMP_RNDD && pstr->negative)
+ || (rnd == GMP_RNDU && !pstr->negative))))
+ {
+ /* Some significant digits might have been forgotten, if so result
+ is not exact. */
+ size_t i;
+
+ for (i = pstr_size; exact && i < pstr->prec; i++)
+ exact = pstr->mant[i] == 0;
+ }
+
/* test if rounding is possible, and if so exit the loop */
if (exact || mpfr_can_round_raw (result, ysize,
(pstr->negative) ? -1 : 1,
diff --git a/tests/tset_str.c b/tests/tset_str.c
index e0e0f80ea..c83e4f54e 100644
--- a/tests/tset_str.c
+++ b/tests/tset_str.c
@@ -81,6 +81,24 @@ check_underflow (void)
mpfr_clear (a);
}
+/* Bug found by Christoph Lauter. */
+static void
+bug20081028 (void)
+{
+ mpfr_t x;
+ const char *s = "0.10000000000000000000000000000001E1";
+
+ mpfr_init2 (x, 32);
+ mpfr_set_str (x, "1.00000000000000000006", 10, GMP_RNDU);
+ if (! mpfr_greater_p (x, __gmpfr_one))
+ {
+ printf ("Error in bug20081028:\nExpected %s\nGot ", s);
+ mpfr_dump (x);
+ exit (1);
+ }
+ mpfr_clear (x);
+}
+
int
main (int argc, char *argv[])
{
@@ -845,6 +863,7 @@ main (int argc, char *argv[])
mpfr_clear (y);
check_underflow ();
+ bug20081028 ();
tests_end_mpfr ();
return 0;
diff --git a/tests/tstrtofr.c b/tests/tstrtofr.c
index 3a0862809..2243bef7e 100644
--- a/tests/tstrtofr.c
+++ b/tests/tstrtofr.c
@@ -27,28 +27,7 @@ MA 02110-1301, USA. */
#include "mpfr-test.h"
-static void check_reftable (void);
-static void check_special (void);
-static void check_retval (void);
-static void check_overflow (void);
-static void check_parse (void);
-
-int
-main (int argc, char *argv[])
-{
- tests_start_mpfr ();
-
- check_special();
- check_reftable ();
- check_parse ();
- check_overflow ();
- check_retval ();
-
- tests_end_mpfr ();
- return 0;
-}
-
-void
+static void
check_special (void)
{
mpfr_t x, y;
@@ -551,8 +530,7 @@ static struct dymmy_test {
"1.001000010110011011000101100000101111101001100011101101001111110111000010010110010001100e-16920"}
};
-
-void
+static void
check_reftable ()
{
int i, base;
@@ -597,7 +575,7 @@ check_reftable ()
mpfr_clear (x);
}
-void
+static void
check_parse (void)
{
mpfr_t x;
@@ -951,3 +929,46 @@ check_retval (void)
mpfr_clear (x);
}
+
+/* Bug found by Christoph Lauter (in mpfr_set_str). */
+static void
+bug20081028 (void)
+{
+ mpfr_t x;
+ const char *s = "0.10000000000000000000000000000001E1";
+ int res, err = 0;
+
+ mpfr_init2 (x, 32);
+ res = mpfr_strtofr (x, "1.00000000000000000006", NULL, 10, GMP_RNDU);
+ if (res <= 0)
+ {
+ printf ("Error in bug20081028: expected positive ternary value,"
+ " got %d\n", res);
+ err = 1;
+ }
+ if (! mpfr_greater_p (x, __gmpfr_one))
+ {
+ printf ("Error in bug20081028:\nExpected %s\nGot ", s);
+ mpfr_dump (x);
+ err = 1;
+ }
+ mpfr_clear (x);
+ if (err)
+ exit (1);
+}
+
+int
+main (int argc, char *argv[])
+{
+ tests_start_mpfr ();
+
+ check_special();
+ check_reftable ();
+ check_parse ();
+ check_overflow ();
+ check_retval ();
+ bug20081028 ();
+
+ tests_end_mpfr ();
+ return 0;
+}