random.scm 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber
  3. ; Random number generator, extracted from T sources. Original
  4. ; probably by Richard Kelsey.
  5. ; Tests have shown that this is not particularly random.
  6. (define half-log 14)
  7. (define full-log (* half-log 2))
  8. (define half-mask (- (arithmetic-shift 1 half-log) 1))
  9. (define full-mask (- (arithmetic-shift 1 full-log) 1))
  10. (define index-log 6)
  11. (define random-1 (bitwise-and 314159265 full-mask))
  12. (define random-2 (bitwise-and 271828189 full-mask))
  13. ; (MAKE-RANDOM <seed>) takes an integer seed and returns a procedure of no
  14. ; arguments that returns a new pseudo-random number each time it is called.
  15. ; <Seed> should be between 0 and 2**28 - 1 (exclusive).
  16. (define (make-random seed)
  17. (if (and (integer? seed)
  18. (< 0 seed)
  19. (<= seed full-mask))
  20. (make-random-vector seed
  21. (lambda (vec a b)
  22. (lambda ()
  23. (set! a (randomize a random-1 random-2))
  24. (set! b (randomize b random-2 random-1))
  25. (let* ((index (arithmetic-shift a (- index-log full-log)))
  26. (c (vector-ref vec index)))
  27. (vector-set! vec index b)
  28. c))))
  29. (assertion-violation 'make-random "invalid argument" seed)))
  30. (define (randomize x mult ad)
  31. (bitwise-and (+ (low-bits-of-product x mult) ad)
  32. full-mask))
  33. (define (make-random-vector seed return)
  34. (let* ((size (arithmetic-shift 1 index-log))
  35. (vec (make-vector size 0)))
  36. (do ((i 0 (+ i 1))
  37. (b seed (randomize b random-2 random-1)))
  38. ((>= i size)
  39. (return vec seed b))
  40. (vector-set! vec i b))))
  41. ; Compute low bits of product of two fixnums using only fixnum arithmetic.
  42. ; [x1 x2] * [y1 y2] = [x1y1 (x1y2+x2y1) x2y2]
  43. (define (low-bits-of-product x y)
  44. (let ((x1 (arithmetic-shift x (- 0 half-log)))
  45. (y1 (arithmetic-shift y (- 0 half-log)))
  46. (x2 (bitwise-and x half-mask))
  47. (y2 (bitwise-and y half-mask)))
  48. (bitwise-and (+ (* x2 y2)
  49. (arithmetic-shift (bitwise-and (+ (* x1 y2) (* x2 y1))
  50. half-mask)
  51. half-log))
  52. full-mask)))