summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2016-12-19 16:11:17 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2016-12-19 16:11:17 +0000
commitaec3cddaccff9e146f7ecb2777aff927a1db0980 (patch)
treee07d4e05050b3786188bfbaa3b1f1ffbdd9b5fbc
parent3b45fa5f7a1d47b485a09003509f3b500eaa0b0c (diff)
downloadmpfr-aec3cddaccff9e146f7ecb2777aff927a1db0980.tar.gz
[src/strtofr.c] Fixed bug in mpfr_strtofr(): in round-to-nearest,
the ternary value could be incorrect. [tests/tstrtofr.c] Added test case. (merged changesets from the trunk: r11055, a part of r11056, and r11059,11066-11068) git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/3.1@11069 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r--src/strtofr.c13
-rw-r--r--tests/tstrtofr.c19
2 files changed, 27 insertions, 5 deletions
diff --git a/src/strtofr.c b/src/strtofr.c
index 67f5caa62..a1904cc04 100644
--- a/src/strtofr.c
+++ b/src/strtofr.c
@@ -743,11 +743,14 @@ parsed_string_to_mpfr (mpfr_t x, struct parsed_string *pstr, mpfr_rnd_t rnd)
of the pstr_size most significant digits of pstr->mant, with
equality in case exact is non-zero. */
- /* test if rounding is possible, and if so exit the loop */
- if (exact || mpfr_can_round_raw (result, ysize,
- (pstr->negative) ? -1 : 1,
- ysize_bits - err - 1,
- MPFR_RNDN, rnd, MPFR_PREC(x)))
+ /* test if rounding is possible, and if so exit the loop.
+ Note: we also need to be able to determine the correct ternary value,
+ thus we use the MPFR_PREC(x) + (rnd == MPFR_RNDN) trick.
+ For example if result = xxx...xxx111...111 and rnd = RNDN,
+ then we know the correct rounding is xxx...xx(x+1), but we cannot know
+ the correct ternary value. */
+ if (exact || mpfr_round_p (result, ysize, ysize_bits - err - 1,
+ MPFR_PREC(x) + (rnd == MPFR_RNDN)))
break;
next_loop:
diff --git a/tests/tstrtofr.c b/tests/tstrtofr.c
index 97575413a..46b76c625 100644
--- a/tests/tstrtofr.c
+++ b/tests/tstrtofr.c
@@ -1191,6 +1191,24 @@ bug20120829 (void)
mpfr_clears (e, x1, x2, (mpfr_ptr) 0);
}
+/* Note: the number is 5^47/2^9. */
+static void
+bug20161217 (void)
+{
+ mpfr_t fp, z;
+ static const char * num = "0.1387778780781445675529539585113525390625e31";
+ int inex;
+
+ mpfr_init2 (fp, 110);
+ mpfr_init2 (z, 110);
+ inex = mpfr_strtofr (fp, num, NULL, 10, MPFR_RNDN);
+ MPFR_ASSERTN(inex == 0);
+ mpfr_set_str_binary (z, "10001100001000010011110110011101101001010000001011011110010001010100010100100110111101000010001011001100001101E-9");
+ MPFR_ASSERTN(mpfr_equal_p (fp, z));
+ mpfr_clear (fp);
+ mpfr_clear (z);
+}
+
int
main (int argc, char *argv[])
{
@@ -1205,6 +1223,7 @@ main (int argc, char *argv[])
test20100310 ();
bug20120814 ();
bug20120829 ();
+ bug20161217 ();
tests_end_mpfr ();
return 0;