Spaces:
Sleeping
Sleeping
;;; srfi-27.scm --- Sources of Random Bits | |
;; Copyright (C) 2010 Free Software Foundation, Inc. | |
;; This library is free software; you can redistribute it and/or | |
;; modify it under the terms of the GNU Lesser General Public | |
;; License as published by the Free Software Foundation; either | |
;; version 3 of the License, or (at your option) any later version. | |
;; This library is distributed in the hope that it will be useful, | |
;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
;; Lesser General Public License for more details. | |
;; You should have received a copy of the GNU Lesser General Public | |
;; License along with this library. If not, see | |
;; <http://www.gnu.org/licenses/>. | |
;;; Commentary: | |
;; This module is fully documented in the Guile Reference Manual. | |
;;; Code: | |
(define-module (srfi srfi-27) | |
#:export (random-integer | |
random-real | |
default-random-source | |
make-random-source | |
random-source? | |
random-source-state-ref | |
random-source-state-set! | |
random-source-randomize! | |
random-source-pseudo-randomize! | |
random-source-make-integers | |
random-source-make-reals) | |
#:use-module (srfi srfi-9)) | |
(cond-expand-provide (current-module) '(srfi-27)) | |
(define-record-type :random-source | |
(%make-random-source state) | |
random-source? | |
(state random-source-state set-random-source-state!)) | |
(define (make-random-source) | |
(%make-random-source (seed->random-state 0))) | |
(define (random-source-state-ref s) | |
(random-state->datum (random-source-state s))) | |
(define (random-source-state-set! s state) | |
(set-random-source-state! s (datum->random-state state))) | |
(define (random-source-randomize! s) | |
(let ((time (gettimeofday))) | |
(set-random-source-state! s (seed->random-state | |
(+ (* (car time) 1e6) (cdr time)))))) | |
(define (random-source-pseudo-randomize! s i j) | |
(set-random-source-state! s (seed->random-state (i+j->seed i j)))) | |
(define (i+j->seed i j) | |
(logior (ash (spread i 2) 1) | |
(spread j 2))) | |
(define (spread n amount) | |
(let loop ((result 0) (n n) (shift 0)) | |
(if (zero? n) | |
result | |
(loop (logior result | |
(ash (logand n 1) shift)) | |
(ash n -1) | |
(+ shift amount))))) | |
(define (random-source-make-integers s) | |
(lambda (n) | |
(random n (random-source-state s)))) | |
(define random-source-make-reals | |
(case-lambda | |
((s) | |
(lambda () | |
(let loop () | |
(let ((x (random:uniform (random-source-state s)))) | |
(if (zero? x) | |
(loop) | |
x))))) | |
((s unit) | |
(or (and (real? unit) (< 0 unit 1)) | |
(error "unit must be real between 0 and 1" unit)) | |
(random-source-make-reals s)))) | |
(define default-random-source (make-random-source)) | |
(define random-integer (random-source-make-integers default-random-source)) | |
(define random-real (random-source-make-reals default-random-source)) | |