|
5 | 5 | (provide random-bits random-natural random-integer)
|
6 | 6 |
|
7 | 7 | ;; Random bits are taken in blocks of this size:
|
8 |
| -(define block-bits 29) |
9 |
| -(define block-size (arithmetic-shift 1 block-bits)) |
| 8 | +(define block-bits : Nonnegative-Fixnum 29) |
| 9 | +(define block-size : Natural (arithmetic-shift 1 block-bits)) |
10 | 10 |
|
11 |
| -(: random-bits (Integer -> Natural)) |
12 |
| -(define (random-bits bits) |
| 11 | +(: random-bits (case-> (Integer -> Natural) |
| 12 | + (Integer Pseudo-Random-Generator -> Natural))) |
| 13 | +(define (random-bits bits [prng (current-pseudo-random-generator)]) |
13 | 14 | (cond [(bits . < . 0) (raise-argument-error 'random-bits "Non-Negative-Integer" bits)]
|
14 | 15 | [(bits . = . 0) 0]
|
| 16 | + [(not (fixnum? bits)) (raise-argument-error 'random-bits "reasonably sized integer" bits)] |
| 17 | + [(bits . <= . block-bits) (random (ann (fxlshift 1 bits) Nonnegative-Fixnum) prng)] |
| 18 | + [(bits . <= . (fx* 2 block-bits)) |
| 19 | + ;; this case is not always in the fixnum range on 32-bit platforms |
| 20 | + (define rem-bits (fx- bits block-bits)) |
| 21 | + (bitwise-ior (arithmetic-shift (random block-size prng) rem-bits) |
| 22 | + (random (ann (fxlshift 1 rem-bits) Nonnegative-Fixnum) prng))] |
15 | 23 | [else
|
16 | 24 | (define max-blocks (assert (quotient bits block-bits) index?))
|
17 | 25 | (define rem-bits (remainder bits block-bits))
|
18 | 26 | (let: loop : Natural ([blocks : Nonnegative-Fixnum 0]
|
19 |
| - [r : Natural (random (fxlshift 1 rem-bits))]) |
| 27 | + [r : Natural (random (fxlshift 1 rem-bits) prng)]) |
20 | 28 | (cond [(blocks . fx< . max-blocks)
|
21 | 29 | (loop (fx+ blocks 1)
|
22 | 30 | (bitwise-ior (arithmetic-shift r block-bits)
|
23 |
| - (random block-size)))] |
| 31 | + (random block-size prng)))] |
24 | 32 | [else r]))]))
|
25 | 33 |
|
26 | 34 | (define random-max 4294967087)
|
27 | 35 |
|
28 |
| -(: random-natural (Integer -> Natural)) |
| 36 | +(: random-natural (case-> (Integer -> Natural) |
| 37 | + (Integer Pseudo-Random-Generator -> Natural))) |
29 | 38 | ;; Returns a random integer in the interval [0..n)
|
30 |
| -(define (random-natural n) |
| 39 | +(define (random-natural n [prng (current-pseudo-random-generator)]) |
31 | 40 | (cond
|
32 | 41 | [(n . <= . 0) (raise-argument-error 'random-natural "Positive-Integer" n)]
|
33 |
| - [(n . <= . random-max) (random n)] |
| 42 | + [(n . <= . random-max) (random n prng)] |
34 | 43 | [else
|
35 | 44 | (define bits (integer-length (- n 1)))
|
36 | 45 | (let loop ()
|
37 |
| - (define r (random-bits bits)) |
| 46 | + (define r (random-bits bits prng)) |
38 | 47 | (if (r . >= . n) (loop) r))]))
|
39 | 48 |
|
40 |
| -(: random-integer (Integer Integer -> Integer)) |
41 |
| -(define (random-integer a b) |
| 49 | +(: random-integer (case-> (Integer Integer -> Integer) |
| 50 | + (Integer Integer Pseudo-Random-Generator -> Integer))) |
| 51 | +(define (random-integer a b [prng (current-pseudo-random-generator)]) |
42 | 52 | (let ([a (min a b)] [b (max a b)])
|
43 |
| - (+ a (random-natural (- b a))))) |
| 53 | + (+ a (random-natural (- b a) prng)))) |
0 commit comments