diff options
| author | Karl Heuer | 1994-03-16 06:48:19 +0000 |
|---|---|---|
| committer | Karl Heuer | 1994-03-16 06:48:19 +0000 |
| commit | 78217ef17f31062ff4ea7de57af278acfec12df3 (patch) | |
| tree | 782009922572b1f2fdd666d9ac463743e0bd7058 | |
| parent | 81a63ccc739d542b689f12177d9de9dae0f0e480 (diff) | |
| download | emacs-78217ef17f31062ff4ea7de57af278acfec12df3.tar.gz emacs-78217ef17f31062ff4ea7de57af278acfec12df3.zip | |
(Frandom): Eliminate bias in random number generator.
| -rw-r--r-- | src/fns.c | 21 |
1 files changed, 13 insertions, 8 deletions
| @@ -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 | ||