From 3bb61eb7955b075145731fd6835631b316c770a5 Mon Sep 17 00:00:00 2001 From: vlefevre Date: Tue, 22 Aug 2017 11:57:20 +0000 Subject: [src/urandom.c] Fixed bug reported by Trevor Spiteri: [tests/turandom.c] Added non-regression test. (merged changesets r11218-11219,11221 from the trunk) git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/3.1@11648 280ebfd0-de03-0410-8827-d642c229c3f4 --- src/urandom.c | 8 ++++---- tests/turandom.c | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/urandom.c b/src/urandom.c index 8ca5f043e..0145be52c 100644 --- a/src/urandom.c +++ b/src/urandom.c @@ -87,19 +87,20 @@ mpfr_urandom (mpfr_ptr rop, gmp_randstate_t rstate, mpfr_rnd_t rnd_mode) count_leading_zeros (cnt, rp[0]); cnt -= GMP_NUMB_BITS - DRAW_BITS; } + exp -= cnt; /* no integer overflow */ - if (MPFR_UNLIKELY (exp < emin + cnt)) + if (MPFR_UNLIKELY (exp < emin)) { /* To get here, we have been drawing more than -emin zeros in a row, then return 0 or the smallest representable positive number. The rounding to nearest mode is subtle: - If exp - cnt == emin - 1, the rounding bit is set, except + If exp == emin - 1, the rounding bit is set, except if cnt == DRAW_BITS in which case the rounding bit is outside rp[0] and must be generated. */ if (rnd_mode == MPFR_RNDU || rnd_mode == MPFR_RNDA - || (rnd_mode == MPFR_RNDN && cnt == exp - emin - 1 + || (rnd_mode == MPFR_RNDN && exp == emin - 1 && (cnt != DRAW_BITS || random_rounding_bit (rstate)))) { mpfr_set_ui_2exp (rop, 1, emin - 1, rnd_mode); @@ -111,7 +112,6 @@ mpfr_urandom (mpfr_ptr rop, gmp_randstate_t rstate, mpfr_rnd_t rnd_mode) return -1; } } - exp -= cnt; } MPFR_EXP (rop) = exp; /* Warning: may be outside the current exponent range */ diff --git a/tests/turandom.c b/tests/turandom.c index 53bb7ee47..ec5ff8ff9 100644 --- a/tests/turandom.c +++ b/tests/turandom.c @@ -191,6 +191,24 @@ bug20100914 (void) gmp_randclear (s); } +/* non-regression test for bug reported by Trevor Spiteri + https://sympa.inria.fr/sympa/arc/mpfr/2017-01/msg00020.html */ +static void +bug20170123 (void) +{ + mpfr_t x; + mpfr_exp_t emin; + + emin = mpfr_get_emin (); + mpfr_set_emin (-7); + mpfr_init2 (x, 53); + gmp_randseed_ui (mpfr_rands, 398); + mpfr_urandom (x, mpfr_rands, MPFR_RNDN); + MPFR_ASSERTN(mpfr_cmp_ui_2exp (x, 1, -8) == 0); + mpfr_clear (x); + mpfr_set_emin (emin); +} + int main (int argc, char *argv[]) { @@ -244,6 +262,8 @@ main (int argc, char *argv[]) bug20100914 (); + bug20170123 (); + tests_end_mpfr (); return 0; } -- cgit v1.2.1