[plt-scheme] random numbers (was: A curious evaluation order (?) bug)
Thanks, Doug and Chongkai, for the discussion on random numbers and
SRFI-27...
At Sun, 30 Dec 2007 14:11:33 -0700, "Doug Williams" wrote:
> 1) Make both random sources have the same 'type' - i.e.
> make-pseudo-random-generator from PLT Scheme and make-random-source from
> SRFI 27 should return objects that can be used in either context because
> they are the same implementation.
Done in SVN for 3.99.0.8.
The main missing piece was `vector->pseudo-random-generator!', which
installs a given state into an existing generator (instead of creating
a new one). Also, `random' needed to accept integers up to 4294967087
to match the old SRFI-27 implementation.
> 2) Make PLT Scheme random routines (like random and random-seed) be able to
> accept a random-source as an argument. It seems wasteful to continually
> parameterize current-pseudo-random-stream to fake passing random (or
> random-seed) an argument, which is one of the main kludges I was referring
> to.
Also done. I don't think that `parameterize' is a "fake" way of passing
an argument, but I concede that passing a generator directly is faster.
The new SRFI-27 `random-integer' seems about 3 times as fast as in v372
(which was about 5 times as fast as the old implementation in v371).
> 3) Implement a SRFI 27 pseudo randomize in PLT Scheme (because it is more
> robust than a single seed) and then implement random-seed in terms of it.
> For example, we might define (random-seed s k) as being equivalent to
> (random-source-pseudo-randomize! s k 0).
I took a slightly different approach on this point and for
`random-integer' on large integers. Instead of changing MzScheme, I
adjusted the SRFI-27 implementation to combine the old
`mrg32k3a-random-large' and `mrg32k3a-pseudo-randomize-state' with the
MzScheme generator. That resolves the mismatch in techniques for
generating large integers and installing a pseudo-randomization.
As a sanity check, the test below produces the same output in v371 (old
SRFI-27 implementation) and 3.99.0.8.
Matthew
----------------------------------------
(module gen mzscheme
(require (lib "random-bits.ss" "srfi/27"))
(define (gen rand)
(let loop ([i 10000])
(unless (zero? i)
(write (rand))
(newline)
(loop (sub1 i)))))
(let ([rs (make-random-source)])
(random-source-pseudo-randomize! rs 42 1024)
(gen (let ([random-integer
(random-source-make-integers rs)])
(lambda () (random-integer 4096))))
(random-source-pseudo-randomize! rs 1024 42)
(gen (let ([random-integer
(random-source-make-integers rs)])
(lambda () (random-integer (expt 2 50)))))
(random-source-pseudo-randomize! rs 500 7)
(gen (random-source-make-reals rs))))