[plt-scheme] random numbers (was: A curious evaluation order (?) bug)

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Mon Dec 31 06:41:04 EST 2007

Thanks, Doug and Chongkai, for the discussion on random numbers and

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

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



(module gen mzscheme
  (require (lib "random-bits.ss" "srfi/27"))

  (define (gen rand)
    (let loop ([i 10000])
      (unless (zero? i)
        (write (rand))
        (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))))

Posted on the users mailing list.