aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarl Heuer1994-03-16 06:48:19 +0000
committerKarl Heuer1994-03-16 06:48:19 +0000
commit78217ef17f31062ff4ea7de57af278acfec12df3 (patch)
tree782009922572b1f2fdd666d9ac463743e0bd7058
parent81a63ccc739d542b689f12177d9de9dae0f0e480 (diff)
downloademacs-78217ef17f31062ff4ea7de57af278acfec12df3.tar.gz
emacs-78217ef17f31062ff4ea7de57af278acfec12df3.zip
(Frandom): Eliminate bias in random number generator.
-rw-r--r--src/fns.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/src/fns.c b/src/fns.c
index 43ff91d183e..555cae98afb 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -55,24 +55,29 @@ With argument t, set the random number seed from the current time and pid.")
55 Lisp_Object limit; 55 Lisp_Object limit;
56{ 56{
57 int val; 57 int val;
58 unsigned long denominator;
58 extern long random (); 59 extern long random ();
59 extern srandom (); 60 extern srandom ();
60 extern long time (); 61 extern long time ();
61 62
62 if (EQ (limit, Qt)) 63 if (EQ (limit, Qt))
63 srandom (getpid () + time (0)); 64 srandom (getpid () + time (0));
64 val = random (); 65 if (XTYPE (limit) == Lisp_Int && XINT (limit) > 0)
65 if (XTYPE (limit) == Lisp_Int && XINT (limit) != 0)
66 { 66 {
67 /* Try to take our random number from the higher bits of VAL, 67 /* Try to take our random number from the higher bits of VAL,
68 not the lower, since (says Gentzel) the low bits of `random' 68 not the lower, since (says Gentzel) the low bits of `random'
69 are less random than the higher ones. */ 69 are less random than the higher ones. We do this by using the
70 val &= 0xfffffff; /* Ensure positive. */ 70 quotient rather than the remainder. At the high end of the RNG
71 val >>= 5; 71 it's possible to get a quotient larger than limit; discarding
72 if (XINT (limit) < 10000) 72 these values eliminates the bias that would otherwise appear
73 val >>= 6; 73 when using a large limit. */
74 val %= XINT (limit); 74 denominator = (unsigned long)0x80000000 / XFASTINT (limit);
75 do
76 val = (random () & 0x7fffffff) / denominator;
77 while (val >= limit);
75 } 78 }
79 else
80 val = random ();
76 return make_number (val); 81 return make_number (val);
77} 82}
78 83