; Copyright (C) 2010 Dave Griffiths : See LICENCE file ; from http://www.cs.grinnell.edu/~stone/events/scheme-workshop/random.html (define random-maker (let* ((multiplier 48271) (modulus 2147483647) (apply-congruence (lambda (current-seed) (let ((candidate (modulo (* current-seed multiplier) modulus))) (if (zero? candidate) modulus candidate)))) (coerce (lambda (proposed-seed) (if (integer? proposed-seed) (- modulus (modulo proposed-seed modulus)) 19860617)))) ;; an arbitrarily chosen birthday (lambda (initial-seed) (let ((seed (coerce initial-seed))) (lambda args (cond ((null? args) (set! seed (apply-congruence seed)) (/ (- modulus seed) modulus)) ((null? (cdr args)) (let* ((proposed-top (ceiling (abs (car args)))) (exact-top (if (inexact? proposed-top) (inexact->exact proposed-top) proposed-top)) (top (if (zero? exact-top) 1 exact-top))) (set! seed (apply-congruence seed)) (inexact->exact (floor (* top (/ seed modulus)))))) ((eq? (cadr args) 'reset) (set! seed (coerce (car args)))) (else (display "random: unrecognized message") (newline)))))))) (define rand (random-maker 19781116)) ;; another arbitrarily chosen birthday (define (rndf) (* (rand 10000) 0.0001)) (define (crndf) (* (- (rndf) 0.5) 2)) (define (rndvec) (vector (rndf) (rndf) (rndf))) (define (crndvec) (vector (crndf) (crndf) (crndf))) (define (srndvec) (let loop ((v (crndvec))) (if (> (vmag v) 1) ; todo: use non sqrt version (loop (crndvec)) v))) (define (hsrndvec) (let loop ((v (crndvec))) (let ((l (vmag v))) (if (or (> l 1) (eq? l 0)) (loop (crndvec)) (vdiv v l))))) ;; gaussian (define (grndf) (let loop ((x (crndf)) (y (crndf))) (let ((l (+ (* x x) (* y y)))) (if (or (>= l 1) (eq? l 0)) (loop (crndf) (crndf)) (* (sqrt (/ (* -2 (log l)) l)) x))))) (define (grndvec) (vector (grndf) (grndf) (grndf))) ; return a line on the hemisphere (define (rndhemi n) (let loop ((v (srndvec))) (if (> (vdot n v) 0) v (loop (srndvec))))) (define (hrndhemi n) (let loop ((v (hsrndvec))) (if (> (vdot n v) 0) v (loop (hsrndvec)))))