cs: fix random on 4294967087

On a 64-bit machine, the problem was a `<` versus `<=`.
On a 32-bit machine where 4294967087 is not a fixnum, the
problem was in how bignums are handled.
This commit is contained in:
Matthew Flatt 2020-10-17 16:56:03 -06:00
parent 9f5c0cbb07
commit 8baf16c093
2 changed files with 18 additions and 7 deletions

View File

@ -2736,6 +2736,10 @@
(test '#(1062645402 3593208522 3838676319 2291995347 179540564 3081399108)
pseudo-random-generator->vector (current-pseudo-random-generator)))
(test 1110944503
random 4294967087 (vector->pseudo-random-generator
'#(2182378604 1199273501 1921976687 2184096762 3398188531 1221198170)))
(test #t = 0 0)
(test #f = 0 (expt 2 32))
(test #f = (expt 2 32) 0)

View File

@ -2777,19 +2777,26 @@
(random-double s)]
[(s x)
(define (random-integer s x)
(modulo (let loop ([bits (integer-length x)])
(cond
[(<= bits 0) 0]
[else (bitwise-ior (bitwise-arithmetic-shift-left (loop (- bits 24)) 24)
(random-int s #xFFFFFF))]))
x))
(let ([bits (integer-length x)])
(let loop ([shift 0])
(cond
[(<= bits shift) 0]
[else
;; Assuming that a `uptr` is at least 32 bits:
(bitwise-ior (loop (+ shift 32))
(let ([n (bitwise-bit-field x shift (+ shift 32))])
(if (zero? n)
0
(bitwise-arithmetic-shift-left
(random-int s n)
shift))))]))))
(unless (is-pseudo-random-generator? s) ($oops who "not a pseudo-random generator ~s" s))
(cond
[(fixnum? x)
(unless (fxpositive? x) ($oops who "not a positive exact integer ~s" x))
(meta-cond
[(<= (constant most-negative-fixnum) 4294967087 (constant most-positive-fixnum))
(if (fx< x 4294967087)
(if (fx<= x 4294967087)
(random-int s x)
(random-integer s x))]
[else