srfi-27.scm 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. ;;; srfi-27.scm --- Sources of Random Bits
  2. ;; Copyright (C) 2010 Free Software Foundation, Inc.
  3. ;; This library is free software; you can redistribute it and/or
  4. ;; modify it under the terms of the GNU Lesser General Public
  5. ;; License as published by the Free Software Foundation; either
  6. ;; version 3 of the License, or (at your option) any later version.
  7. ;; This library is distributed in the hope that it will be useful,
  8. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. ;; Lesser General Public License for more details.
  11. ;; You should have received a copy of the GNU Lesser General Public
  12. ;; License along with this library. If not, see
  13. ;; <http://www.gnu.org/licenses/>.
  14. ;;; Commentary:
  15. ;; This module is fully documented in the Guile Reference Manual.
  16. ;;; Code:
  17. (define-module (srfi srfi-27)
  18. #:export (random-integer
  19. random-real
  20. default-random-source
  21. make-random-source
  22. random-source?
  23. random-source-state-ref
  24. random-source-state-set!
  25. random-source-randomize!
  26. random-source-pseudo-randomize!
  27. random-source-make-integers
  28. random-source-make-reals)
  29. #:use-module (srfi srfi-9))
  30. (define-record-type :random-source
  31. (%make-random-source state)
  32. random-source?
  33. (state random-source-state set-random-source-state!))
  34. (define (make-random-source)
  35. (%make-random-source (seed->random-state 0)))
  36. (define (random-source-state-ref s)
  37. (random-state->datum (random-source-state s)))
  38. (define (random-source-state-set! s state)
  39. (set-random-source-state! s (datum->random-state state)))
  40. (define (random-source-randomize! s)
  41. (let ((time (gettimeofday)))
  42. (set-random-source-state! s (seed->random-state
  43. (+ (* (car time) 1e6) (cdr time))))))
  44. (define (random-source-pseudo-randomize! s i j)
  45. (set-random-source-state! s (seed->random-state (i+j->seed i j))))
  46. (define (i+j->seed i j)
  47. (logior (ash (spread i 2) 1)
  48. (spread j 2)))
  49. (define (spread n amount)
  50. (let loop ((result 0) (n n) (shift 0))
  51. (if (zero? n)
  52. result
  53. (loop (logior result
  54. (ash (logand n 1) shift))
  55. (ash n -1)
  56. (+ shift amount)))))
  57. (define (random-source-make-integers s)
  58. (lambda (n)
  59. (random n (random-source-state s))))
  60. (define random-source-make-reals
  61. (case-lambda
  62. ((s)
  63. (lambda ()
  64. (let loop ()
  65. (let ((x (random:uniform (random-source-state s))))
  66. (if (zero? x)
  67. (loop)
  68. x)))))
  69. ((s unit)
  70. (or (and (real? unit) (< 0 unit 1))
  71. (error "unit must be real between 0 and 1" unit))
  72. (random-source-make-reals s))))
  73. (define default-random-source (make-random-source))
  74. (define random-integer (random-source-make-integers default-random-source))
  75. (define random-real (random-source-make-reals default-random-source))