Subject: Re: bug#9118: 23.3.50; Don't seed the RNG in message-unique-id

From: Leo <[email-masked]>
Date: Thu, 21 Jul 2011 23:58:46 +0800

On 2011-07-21 19:57 +0800, Juanma Barranquero wrote:
> Many systems (languages, etc.) have a facility to seed the RNG with a
> specific seed (saved from a previous run, for example), so you can
> have repeated runs with the exact same sequence of random numbers, if
> needed. That can be useful for simulation, testing, etc.
>
> AFAIK, the Emacs RNG does not allow that at the lisp level, so it
> would be better to automatically seed it and remove the many (random
> t) calls, which, as has been pointed out, can in fact be harmful for
> the quality of the generated random number series, if called
> repeatedly.

I agree completely.

How about something along these lines? (note: before this patch (random
1.0) is equivalent to (random most-positive-fixnum)).

=== modified file 'src/fns.c'
--- src/fns.c	2011-07-05 02:51:15 +0000
+++ src/fns.c	2011-07-21 15:47:30 +0000
@@ -69,15 +69,15 @@
 }
 
 DEFUN ("random", Frandom, Srandom, 0, 1, 0,
-       doc: /* Return a pseudo-random number.
+       doc: /* Return a non-negative pseudo-random number less than LIMIT.
 All integers representable in Lisp are equally likely.
   On most systems, this is 29 bits' worth.
-With positive integer LIMIT, return random number in interval [0,LIMIT).
-With argument t, set the random number seed from the current time and pid.
-Other values of LIMIT are ignored.  */)
+Optional argument LIMIT defaults to `most-positive-fixnum'.
+With argument t, set the random number seed from the current time
+  and pid and return nil.  */)
   (Lisp_Object limit)
 {
-  EMACS_INT val;
+  EMACS_INT val, denominator;
   Lisp_Object lispy_val;
 
   if (EQ (limit, Qt))
@@ -85,24 +85,28 @@
       EMACS_TIME t;
       EMACS_GET_TIME (t);
       seed_random (getpid () ^ EMACS_SECS (t) ^ EMACS_USECS (t));
+      return Qnil;
     }
 
-  if (NATNUMP (limit) && XFASTINT (limit) != 0)
-    {
-      /* Try to take our random number from the higher bits of VAL,
-	 not the lower, since (says Gentzel) the low bits of `random'
-	 are less random than the higher ones.  We do this by using the
-	 quotient rather than the remainder.  At the high end of the RNG
-	 it's possible to get a quotient larger than n; discarding
-	 these values eliminates the bias that would otherwise appear
-	 when using a large n.  */
-      EMACS_INT denominator = (INTMASK + 1) / XFASTINT (limit);
-      do
-	val = get_random () / denominator;
-      while (val >= XFASTINT (limit));
-    }
-  else
-    val = get_random ();
+  if (NILP (limit))
+    XSETINT (limit, MOST_POSITIVE_FIXNUM);
+
+  CHECK_NATNUM (limit);
+
+  if (XFASTINT (limit) == 0)
+    xsignal1 (Qargs_out_of_range, limit);
+
+  /* Try to take our random number from the higher bits of VAL,
+     not the lower, since (says Gentzel) the low bits of `random'
+     are less random than the higher ones.  We do this by using the
+     quotient rather than the remainder.  At the high end of the RNG
+     it's possible to get a quotient larger than n; discarding
+     these values eliminates the bias that would otherwise appear
+     when using a large n.  */
+  denominator = (INTMASK + 1) / XFASTINT (limit);
+  do
+    val = get_random () / denominator;
+  while (val >= XFASTINT (limit));
   XSETINT (lispy_val, val);
   return lispy_val;
 }
@@ -5009,4 +5013,5 @@
 void
 init_fns (void)
 {
+  Frandom (Qt);
 }