changeset 16280:5c08684c856f

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.
author Bruno Haible <bruno@clisp.org>
date Sat, 14 Jan 2012 15:15:28 +0100
parents 11a41c8839e3
children 8dbc5c156eaa
files ChangeLog config/srclist.txt doc/posix-functions/initstate.texi doc/posix-functions/random.texi doc/posix-functions/setstate.texi doc/posix-functions/srandom.texi lib/random.c lib/stdlib.in.h m4/random.m4 m4/stdlib_h.m4 modules/random modules/stdlib
diffstat 12 files changed, 341 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2012-01-14  Bruno Haible  <bruno@clisp.org>
+
+	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  <bruno@clisp.org>
 
 	random_r: Use common idioms.
--- a/config/srclist.txt
+++ b/config/srclist.txt
@@ -198,6 +198,7 @@
 #$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
--- 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
-@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
+
+Portability problems not fixed by Gnulib:
+@itemize
+@end itemize
--- 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
-@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
+
+Portability problems not fixed by Gnulib:
+@itemize
+@end itemize
--- 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
-@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
+
+Portability problems not fixed by Gnulib:
+@itemize
+@end itemize
--- 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
-@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
+
+Portability problems not fixed by Gnulib:
+@itemize
+@end itemize
new file mode 100644
--- /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 <http://www.gnu.org/licenses/>.  */
+
+/*
+ * 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 <config.h>
+
+/* Specification.  */
+#include <stdlib.h>
+
+#include <stdint.h>
+#include <time.h>
+
+/* 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;
+}
--- a/lib/stdlib.in.h
+++ b/lib/stdlib.in.h
@@ -504,6 +504,67 @@
 # 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)
new file mode 100644
--- /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], [
+  :
+])
--- 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 @@
   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 @@
   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])
new file mode 100644
--- /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:
+<stdlib.h>
+
+License:
+LGPL
+
+Maintainer:
+Bruno Haible, glibc
--- a/modules/stdlib
+++ b/modules/stdlib
@@ -49,6 +49,7 @@
 	      -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 @@
 	      -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' \