From e2ee61c4fa5854e218eaeedef1dcedf26e965fba Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sat, 14 Jan 2012 15:15:28 +0100 Subject: [PATCH] New module 'random'. * lib/stdlib.in.h (random, srandom, initstate, setstate): New declarations. * lib/random.c: New file, based on glibc/stdlib/random.c. * m4/random.m4: New file. * m4/stdlib_h.m4 (gl_STDLIB_H_DEFAULTS): Initialize GNULIB_RANDOM, HAVE_RANDOM. * modules/stdlib (Makefile.am): Substitute GNULIB_RANDOM, HAVE_RANDOM. * modules/random: New file. * config/srclist.txt: Add an entry for random.c. * doc/posix-functions/random.texi: Mention the 'random' module. * doc/posix-functions/initstate.texi: Likewise. * doc/posix-functions/setstate.texi: Likewise. * doc/posix-functions/srandom.texi: Likewise. --- ChangeLog | 17 ++++ config/srclist.txt | 1 + doc/posix-functions/initstate.texi | 8 +- doc/posix-functions/random.texi | 8 +- doc/posix-functions/setstate.texi | 8 +- doc/posix-functions/srandom.texi | 8 +- lib/random.c | 187 +++++++++++++++++++++++++++++++++++++ lib/stdlib.in.h | 61 ++++++++++++ m4/random.m4 | 20 ++++ m4/stdlib_h.m4 | 4 +- modules/random | 30 ++++++ modules/stdlib | 2 + 12 files changed, 337 insertions(+), 17 deletions(-) create mode 100644 lib/random.c create mode 100644 m4/random.m4 create mode 100644 modules/random diff --git a/ChangeLog b/ChangeLog index f1e4fdcf9..8404e064e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2012-01-14 Bruno Haible + + New module 'random'. + * lib/stdlib.in.h (random, srandom, initstate, setstate): New + declarations. + * lib/random.c: New file, based on glibc/stdlib/random.c. + * m4/random.m4: New file. + * m4/stdlib_h.m4 (gl_STDLIB_H_DEFAULTS): Initialize GNULIB_RANDOM, + HAVE_RANDOM. + * modules/stdlib (Makefile.am): Substitute GNULIB_RANDOM, HAVE_RANDOM. + * modules/random: New file. + * config/srclist.txt: Add an entry for random.c. + * doc/posix-functions/random.texi: Mention the 'random' module. + * doc/posix-functions/initstate.texi: Likewise. + * doc/posix-functions/setstate.texi: Likewise. + * doc/posix-functions/srandom.texi: Likewise. + 2012-01-12 Bruno Haible random_r: Use common idioms. diff --git a/config/srclist.txt b/config/srclist.txt index abea167fb..ba3143a3c 100644 --- a/config/srclist.txt +++ b/config/srclist.txt @@ -198,6 +198,7 @@ $GNUORG/disclaim.program doc/Copyright #$LIBCSRC/posix/glob.h lib gpl (glob-libc.h in gnulib) # #$LIBCSRC/stdlib/putenv.c lib gpl +#$LIBCSRC/stdlib/random.c lib gpl #$LIBCSRC/stdlib/random_r.c lib gpl #$LIBCSRC/stdlib/rpmatch.c lib gpl #$LIBCSRC/stdlib/strtol.c lib gpl diff --git a/doc/posix-functions/initstate.texi b/doc/posix-functions/initstate.texi index a405d7921..fc7ef2df7 100644 --- a/doc/posix-functions/initstate.texi +++ b/doc/posix-functions/initstate.texi @@ -4,15 +4,15 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/initstate.html} -Gnulib module: --- +Gnulib module: random Portability problems fixed by Gnulib: @itemize +@item +This function is missing on some platforms: +Solaris 2.4, mingw, MSVC 9. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on some platforms: -Solaris 2.4, mingw, MSVC 9. @end itemize diff --git a/doc/posix-functions/random.texi b/doc/posix-functions/random.texi index cea4e049d..cd72e5dd4 100644 --- a/doc/posix-functions/random.texi +++ b/doc/posix-functions/random.texi @@ -4,15 +4,15 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/random.html} -Gnulib module: --- +Gnulib module: random Portability problems fixed by Gnulib: @itemize +@item +This function is missing on some platforms: +Solaris 2.4, mingw, MSVC 9. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on some platforms: -Solaris 2.4, mingw, MSVC 9. @end itemize diff --git a/doc/posix-functions/setstate.texi b/doc/posix-functions/setstate.texi index e6dec8202..085253e40 100644 --- a/doc/posix-functions/setstate.texi +++ b/doc/posix-functions/setstate.texi @@ -4,15 +4,15 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/setstate.html} -Gnulib module: --- +Gnulib module: random Portability problems fixed by Gnulib: @itemize +@item +This function is missing on some platforms: +Solaris 2.4, mingw, MSVC 9. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on some platforms: -Solaris 2.4, mingw, MSVC 9. @end itemize diff --git a/doc/posix-functions/srandom.texi b/doc/posix-functions/srandom.texi index 23d6f0d95..ee335d146 100644 --- a/doc/posix-functions/srandom.texi +++ b/doc/posix-functions/srandom.texi @@ -4,15 +4,15 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/srandom.html} -Gnulib module: --- +Gnulib module: random Portability problems fixed by Gnulib: @itemize +@item +This function is missing on some platforms: +Solaris 2.4, mingw, MSVC 9. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on some platforms: -Solaris 2.4, mingw, MSVC 9. @end itemize diff --git a/lib/random.c b/lib/random.c new file mode 100644 index 000000000..02661065e --- /dev/null +++ b/lib/random.c @@ -0,0 +1,187 @@ +/* Family of functions for random integers. + Copyright (C) 1995-1997, 2000-2002, 2012 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* + * This is derived from the Berkeley source: + * @(#)random.c 5.5 (Berkeley) 7/6/88 + * It was reworked for the GNU C Library by Roland McGrath. + * Rewritten to use reentrant functions by Ulrich Drepper, 1995. + */ + +/* + Copyright (C) 1983 Regents of the University of California. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 4. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE.*/ + +#include + +/* Specification. */ +#include + +#include +#include + +/* This file can assume the 'struct random_data' and associated *_r functions + from gnulib. */ + +/* Linear congruential. */ +#define TYPE_0 0 +#define BREAK_0 8 +#define DEG_0 0 +#define SEP_0 0 + +/* x**7 + x**3 + 1. */ +#define TYPE_1 1 +#define BREAK_1 32 +#define DEG_1 7 +#define SEP_1 3 + +/* x**15 + x + 1. */ +#define TYPE_2 2 +#define BREAK_2 64 +#define DEG_2 15 +#define SEP_2 1 + +/* x**31 + x**3 + 1. */ +#define TYPE_3 3 +#define BREAK_3 128 +#define DEG_3 31 +#define SEP_3 3 + +/* x**63 + x + 1. */ +#define TYPE_4 4 +#define BREAK_4 256 +#define DEG_4 63 +#define SEP_4 1 + +/* Array versions of the above information to make code run faster. + Relies on fact that TYPE_i == i. */ + +#define MAX_TYPES 5 /* Max number of types above. */ + +/* Initially, everything is set up as if from: + initstate(1, randtbl, 128); + Note that this initialization takes advantage of the fact that srandom + advances the front and rear pointers 10*rand_deg times, and hence the + rear pointer which starts at 0 will also end up at zero; thus the zeroth + element of the state information, which contains info about the current + position of the rear pointer is just + (MAX_TYPES * (rptr - state)) + TYPE_3 == TYPE_3. */ + +static int32_t randtbl[DEG_3 + 1] = + { + TYPE_3, + + -1726662223, 379960547, 1735697613, 1040273694, 1313901226, + 1627687941, -179304937, -2073333483, 1780058412, -1989503057, + -615974602, 344556628, 939512070, -1249116260, 1507946756, + -812545463, 154635395, 1388815473, -1926676823, 525320961, + -1009028674, 968117788, -123449607, 1284210865, 435012392, + -2017506339, -911064859, -370259173, 1132637927, 1398500161, + -205601318, + }; + +static struct random_data generator = + { +/* FPTR and RPTR are two pointers into the state info, a front and a rear + pointer. These two pointers are always rand_sep places aparts, as they + cycle through the state information. (Yes, this does mean we could get + away with just one pointer, but the code for random is more efficient + this way). The pointers are left positioned as they would be from the call: + initstate(1, randtbl, 128); + (The position of the rear pointer, rptr, is really 0 (as explained above + in the initialization of randtbl) because the state table pointer is set + to point to randtbl[1] (as explained below).) */ + + /* fptr */ &randtbl[SEP_3 + 1], + /* rptr */ &randtbl[1], + +/* The following things are the pointer to the state information table, + the type of the current generator, the degree of the current polynomial + being used, and the separation between the two pointers. + Note that for efficiency of random, we remember the first location of + the state information, not the zeroth. Hence it is valid to access + state[-1], which is used to store the type of the R.N.G. + Also, we remember the last location, since this is more efficient than + indexing every time to find the address of the last element to see if + the front and rear pointers have wrapped. */ + + /* state */ &randtbl[1], + + /* rand_type */ TYPE_3, + /* rand_deg */ DEG_3, + /* rand_sep */ SEP_3, + + /* end_ptr */ &randtbl[sizeof (randtbl) / sizeof (randtbl[0])] +}; + +long +random (void) +{ + int32_t val; + + if (random_r (&generator, &val) < 0) + abort (); /* should not happen */ + return val; +} + +void +srandom (unsigned int seed) +{ + (void) srandom_r (seed, &generator); /* may fail! */ +} + +char * +initstate (unsigned int seed, char *buf, size_t buf_size) +{ + char *old_state = (char *) ((int32_t *) generator.state - 1); + if (initstate_r (seed, buf, buf_size, &generator) < 0) + return NULL; /* failed */ + return old_state; +} + +char * +setstate (char *arg_state) +{ + char *old_state = (char *) ((int32_t *) generator.state - 1); + if (setstate_r (arg_state, &generator) < 0) + return NULL; /* failed */ + return old_state; +} diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h index 0a439e1b0..c25ce0e69 100644 --- a/lib/stdlib.in.h +++ b/lib/stdlib.in.h @@ -504,6 +504,67 @@ _GL_CXXALIASWARN (putenv); # endif #endif + +#if @GNULIB_RANDOM@ +# if !@HAVE_RANDOM@ +_GL_FUNCDECL_SYS (random, long, (void)); +# endif +_GL_CXXALIAS_SYS (random, long, (void)); +_GL_CXXALIASWARN (random); +#elif defined GNULIB_POSIXCHECK +# undef random +# if HAVE_RAW_DECL_RANDOM +_GL_WARN_ON_USE (random, "random is unportable - " + "use gnulib module random for portability"); +# endif +#endif + +#if @GNULIB_RANDOM@ +# if !@HAVE_RANDOM@ +_GL_FUNCDECL_SYS (srandom, void, (unsigned int seed)); +# endif +_GL_CXXALIAS_SYS (srandom, void, (unsigned int seed)); +_GL_CXXALIASWARN (srandom); +#elif defined GNULIB_POSIXCHECK +# undef srandom +# if HAVE_RAW_DECL_SRANDOM +_GL_WARN_ON_USE (srandom, "srandom is unportable - " + "use gnulib module random for portability"); +# endif +#endif + +#if @GNULIB_RANDOM@ +# if !@HAVE_RANDOM@ +_GL_FUNCDECL_SYS (initstate, char *, + (unsigned int seed, char *buf, size_t buf_size) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (initstate, char *, + (unsigned int seed, char *buf, size_t buf_size)); +_GL_CXXALIASWARN (initstate); +#elif defined GNULIB_POSIXCHECK +# undef initstate +# if HAVE_RAW_DECL_INITSTATE_R +_GL_WARN_ON_USE (initstate, "initstate is unportable - " + "use gnulib module random for portability"); +# endif +#endif + +#if @GNULIB_RANDOM@ +# if !@HAVE_RANDOM@ +_GL_FUNCDECL_SYS (setstate, char *, (char *arg_state) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (setstate, char *, (char *arg_state)); +_GL_CXXALIASWARN (setstate); +#elif defined GNULIB_POSIXCHECK +# undef setstate +# if HAVE_RAW_DECL_SETSTATE_R +_GL_WARN_ON_USE (setstate, "setstate is unportable - " + "use gnulib module random for portability"); +# endif +#endif + + #if @GNULIB_RANDOM_R@ # if @REPLACE_RANDOM_R@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) diff --git a/m4/random.m4 b/m4/random.m4 new file mode 100644 index 000000000..c5fd0a7f5 --- /dev/null +++ b/m4/random.m4 @@ -0,0 +1,20 @@ +# random.m4 serial 1 +dnl Copyright (C) 2012 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_RANDOM], +[ + AC_REQUIRE([gl_STDLIB_H_DEFAULTS]) + + AC_CHECK_FUNCS([random]) + if test $ac_cv_func_random = no; then + HAVE_RANDOM=0 + fi +]) + +# Prerequisites of lib/random.c. +AC_DEFUN([gl_PREREQ_RANDOM], [ + : +]) diff --git a/m4/stdlib_h.m4 b/m4/stdlib_h.m4 index 85f7126d3..d75a64b34 100644 --- a/m4/stdlib_h.m4 +++ b/m4/stdlib_h.m4 @@ -1,4 +1,4 @@ -# stdlib_h.m4 serial 40 +# stdlib_h.m4 serial 41 dnl Copyright (C) 2007-2012 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -54,6 +54,7 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS], GNULIB_PTSNAME=0; AC_SUBST([GNULIB_PTSNAME]) GNULIB_PTSNAME_R=0; AC_SUBST([GNULIB_PTSNAME_R]) GNULIB_PUTENV=0; AC_SUBST([GNULIB_PUTENV]) + GNULIB_RANDOM=0; AC_SUBST([GNULIB_RANDOM]) GNULIB_RANDOM_R=0; AC_SUBST([GNULIB_RANDOM_R]) GNULIB_REALLOC_POSIX=0; AC_SUBST([GNULIB_REALLOC_POSIX]) GNULIB_REALPATH=0; AC_SUBST([GNULIB_REALPATH]) @@ -81,6 +82,7 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS], HAVE_POSIX_OPENPT=1; AC_SUBST([HAVE_POSIX_OPENPT]) HAVE_PTSNAME=1; AC_SUBST([HAVE_PTSNAME]) HAVE_PTSNAME_R=1; AC_SUBST([HAVE_PTSNAME_R]) + HAVE_RANDOM=1; AC_SUBST([HAVE_RANDOM]) HAVE_RANDOM_H=1; AC_SUBST([HAVE_RANDOM_H]) HAVE_RANDOM_R=1; AC_SUBST([HAVE_RANDOM_R]) HAVE_REALPATH=1; AC_SUBST([HAVE_REALPATH]) diff --git a/modules/random b/modules/random new file mode 100644 index 000000000..31925bd35 --- /dev/null +++ b/modules/random @@ -0,0 +1,30 @@ +Description: +global random number generator + +Files: +lib/random.c +m4/random.m4 + +Depends-on: +stdlib +stdint +random_r [test $HAVE_RANDOM = 0] + +configure.ac: +gl_FUNC_RANDOM +if test $HAVE_RANDOM = 0; then + AC_LIBOBJ([random]) + gl_PREREQ_RANDOM +fi +gl_STDLIB_MODULE_INDICATOR([random]) + +Makefile.am: + +Include: + + +License: +LGPL + +Maintainer: +Bruno Haible, glibc diff --git a/modules/stdlib b/modules/stdlib index 4633841ad..f967ef63f 100644 --- a/modules/stdlib +++ b/modules/stdlib @@ -49,6 +49,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \ -e 's/@''GNULIB_PTSNAME''@/$(GNULIB_PTSNAME)/g' \ -e 's/@''GNULIB_PTSNAME_R''@/$(GNULIB_PTSNAME_R)/g' \ -e 's/@''GNULIB_PUTENV''@/$(GNULIB_PUTENV)/g' \ + -e 's/@''GNULIB_RANDOM''@/$(GNULIB_RANDOM)/g' \ -e 's/@''GNULIB_RANDOM_R''@/$(GNULIB_RANDOM_R)/g' \ -e 's/@''GNULIB_REALLOC_POSIX''@/$(GNULIB_REALLOC_POSIX)/g' \ -e 's/@''GNULIB_REALPATH''@/$(GNULIB_REALPATH)/g' \ @@ -76,6 +77,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \ -e 's|@''HAVE_POSIX_OPENPT''@|$(HAVE_POSIX_OPENPT)|g' \ -e 's|@''HAVE_PTSNAME''@|$(HAVE_PTSNAME)|g' \ -e 's|@''HAVE_PTSNAME_R''@|$(HAVE_PTSNAME_R)|g' \ + -e 's|@''HAVE_RANDOM''@|$(HAVE_RANDOM)|g' \ -e 's|@''HAVE_RANDOM_H''@|$(HAVE_RANDOM_H)|g' \ -e 's|@''HAVE_RANDOM_R''@|$(HAVE_RANDOM_R)|g' \ -e 's|@''HAVE_REALPATH''@|$(HAVE_REALPATH)|g' \ -- 2.11.0