|
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