12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- ;;; 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))
|