From ca334cbd97562db39c4942dd96591c0edab4766a Mon Sep 17 00:00:00 2001 From: vlefevre Date: Tue, 15 Sep 2020 08:59:28 +0000 Subject: With mini-gmp, use the standard rand() and srand() functions instead of the POSIX (thus less portable) lrand48() and srand48(). (merged changesets r14114-14116 from the trunk) git-svn-id: https://scm.gforge.inria.fr/anonscm/svn/mpfr/branches/4.1@14118 280ebfd0-de03-0410-8827-d642c229c3f4 --- configure.ac | 6 ------ doc/mini-gmp | 7 +++---- src/mpfr-mini-gmp.c | 42 ++++++++++++++++++++++-------------------- 3 files changed, 25 insertions(+), 30 deletions(-) diff --git a/configure.ac b/configure.ac index 8723fce91..a0e81550f 100644 --- a/configure.ac +++ b/configure.ac @@ -807,12 +807,6 @@ AC_COMPUTE_INT(mini_gmp_numb_bits, [(GMP_NUMB_BITS)], CPPFLAGS="$saved_CPPFLAGS" AC_MSG_RESULT([$mini_gmp_numb_bits bits ($how)]) -dnl We need to check the availability of lrand48 (used by random_limb) -dnl and srand48 (used by gmp_randseed_ui), in particular because these -dnl functions are not part of the ISO C standard. -AC_CHECK_FUNC(lrand48,,AC_MSG_FAILURE([MPFR + mini-gmp requires lrand48])) -AC_CHECK_FUNC(srand48,,AC_MSG_FAILURE([MPFR + mini-gmp requires srand48])) - fi dnl End of setup related to GMP / mini-gmp diff --git a/doc/mini-gmp b/doc/mini-gmp index 1d8d76a08..7e66f23a5 100644 --- a/doc/mini-gmp +++ b/doc/mini-gmp @@ -27,10 +27,9 @@ with before including mpfr.h (or you may want to modify mini-gmp.h). Remark: The random functions provided by MPFR configured with mini-gmp -use the POSIX lrand48() and srand48() functions (the platform needs to -provide them), thus one should avoid mini-gmp if one needs some really -serious random functions. Another consequence is that these functions -are not thread-safe. +use the standard rand() function, thus one should avoid mini-gmp if one +needs some really serious random functions. Another consequence is that +these functions may not be thread-safe. This was tested with MPFR svn r13974 and GMP 6.2.0 on x86_64 GNU/Linux: ============================================================================ diff --git a/src/mpfr-mini-gmp.c b/src/mpfr-mini-gmp.c index abdcb9aa2..8e0533271 100644 --- a/src/mpfr-mini-gmp.c +++ b/src/mpfr-mini-gmp.c @@ -40,9 +40,9 @@ gmp_randinit_default (gmp_randstate_t state) void gmp_randseed_ui (gmp_randstate_t state, unsigned long int seed) { - /* With a portable version of the conversion from unsigned long to long - (at least GCC and Clang optimize this expression to identity). */ - srand48 (seed > LONG_MAX ? -1 - (long) ~seed : (long) seed); + /* Note: We possibly ignore the high-order bits of seed. One should take + that into account when setting GMP_CHECK_RANDOMIZE for the tests. */ + srand ((unsigned int) seed); } #endif @@ -60,26 +60,28 @@ gmp_randinit_set (gmp_randstate_t s1, gmp_randstate_t s2) } #endif +static unsigned int +rand15 (void) +{ + /* With a good PRNG, we could use "rand () % 32768", but let's choose + the following from . Note that + on most platforms, the compiler should generate a shift. */ + return rand () / (RAND_MAX / 32768 + 1); +} + static mp_limb_t random_limb (void) { - /* lrand48() returns a random number in [0, 2^31-1], - but the low 15 bits do not depend on the random seed, - thus it is safer to use the upper bits */ -#if GMP_NUMB_BITS < 32 - /* use the upper GMP_NUMB_BITS bits from lrand48 () */ - return (mp_limb_t) (lrand48 () >> (31 - GMP_NUMB_BITS)); -#elif GMP_NUMB_BITS == 32 - /* use the upper 16 bits from two lrand48 calls */ - return (lrand48 () >> 15) + ((lrand48 () >> 15) << 16); -#elif GMP_NUMB_BITS == 64 - /* use the upper 16 bits from four lrand48 calls */ - return (lrand48 () >> 15) + ((((mp_limb_t) lrand48 ()) >> 15) << 16) - + ((((mp_limb_t) lrand48 ()) >> 15) << 32) - + ((((mp_limb_t) lrand48 ()) >> 15) << 48); -#else -#error "GMP_NUMB_BITS should be 8, 16, 32 or >= 64" -#endif + mp_limb_t r = 0; + int i = GMP_NUMB_BITS; + + while (i > 0) + { + r = (r << 15) | rand15 (); + i -= 15; + } + + return r; } #ifdef WANT_mpz_urandomb -- cgit v1.2.1