diff options
-rw-r--r-- | src/get_d64.c | 9 | ||||
-rw-r--r-- | tests/tget_set_d64.c | 27 |
2 files changed, 36 insertions, 0 deletions
diff --git a/src/get_d64.c b/src/get_d64.c index 03dbfd916..d5fd4d64c 100644 --- a/src/get_d64.c +++ b/src/get_d64.c @@ -347,6 +347,15 @@ mpfr_get_decimal64 (mpfr_srcptr src, mpfr_rnd_t rnd_mode) which corresponds to s=[0.]1000...000 and e=-397 */ if (e < -397) { + if (rnd_mode == MPFR_RNDN && e == -398) + { + /* If 0.5E-398 < |src| < 1E-398 (smallest subnormal), + src should round to +/- 1E-398 in MPFR_RNDN. */ + mpfr_get_str (s, &e, 10, 1, src, MPFR_RNDA); + return e == -398 && s[negative] <= '5' ? + get_decimal64_zero (negative) : + get_decimal64_min (negative); + } if (rnd_mode == MPFR_RNDZ || rnd_mode == MPFR_RNDN || (rnd_mode == MPFR_RNDD && negative == 0) || (rnd_mode == MPFR_RNDU && negative != 0)) diff --git a/tests/tget_set_d64.c b/tests/tget_set_d64.c index 444307756..de35fba4e 100644 --- a/tests/tget_set_d64.c +++ b/tests/tget_set_d64.c @@ -289,6 +289,32 @@ check_overflow (void) exit (1); } +static void +check_tiny (void) +{ + mpfr_t x; + _Decimal64 d; + + /* If 0.5E-398 < |x| < 1E-398 (smallest subnormal), x should round + to +/- 1E-398 in MPFR_RNDN. Note: the midpoint 0.5E-398 between + 0 and 1E-398 is not a representable binary number, so that there + are no tests for it. */ + mpfr_init2 (x, 128); + mpfr_set_str (x, "1E-398", 10, MPFR_RNDZ); + d = mpfr_get_decimal64 (x, MPFR_RNDN); + MPFR_ASSERTN (d == 1.0E-398dd); + mpfr_neg (x, x, MPFR_RNDN); + d = mpfr_get_decimal64 (x, MPFR_RNDN); + MPFR_ASSERTN (d == -1.0E-398dd); + mpfr_set_str (x, "0.5E-398", 10, MPFR_RNDU); + d = mpfr_get_decimal64 (x, MPFR_RNDN); + MPFR_ASSERTN (d == 1.0E-398dd); + mpfr_neg (x, x, MPFR_RNDN); + d = mpfr_get_decimal64 (x, MPFR_RNDN); + MPFR_ASSERTN (d == -1.0E-398dd); + mpfr_clear (x); +} + int main (void) { @@ -306,6 +332,7 @@ main (void) check_random (); check_native (); check_overflow (); + check_tiny (); tests_end_mpfr (); return 0; |