;;;; composite-entropy-source.scm
;;;; Kon Lovett, Apr, '17
#|
=== Composite Entropy Source
==== Usage
(import composite-entropy-source)
==== composite-entropy-source
(composite-entropy-source-constructor [ENTROPY-SOURCE ...] [#:comb-int (COMB-INT INTEGER-COMBINE)] [#:comb-real (COMB-REAL REAL-COMBINE)]) => entropy-source
Returns a new {{entropy-source}} that combines the behaviors of the supplied
{{ENTROPY-SOURCE ...}}.
{{INTEGER-COMBINE}} default is {{(lambda (ints bnd) (modulo (apply + ints) bnd))}}.
{{REAL-COMBINE}} default is {{(lambda (reals prec) (apply * reals))}}.
Does not register the constructed {{entropy-source}}.
Experimental at best.
|#
(module composite-entropy-source
(;export
*composite-entropy-source-constructor
composite-entropy-source-constructor)
(import scheme
(chicken base)
(chicken type)
(chicken keyword)
(chicken fixnum)
(chicken flonum)
(only (chicken string) conc reverse-string-append ->string)
type-errors-basic
(srfi 1)
(srfi 4)
entropy-source
srfi-27-vector-support
(srfi 27))
;;;
(include-relative "srfi-27-common-types")
(: composite-entropy-source-constructor (#!rest -> procedure))
(: *composite-entropy-source-constructor (procedure procedure entropy-source-name string (list-of entropy-source) -> procedure))
;;
(define (pull-rest-argument rest0)
(let loop ((irest rest0) (orest '()))
(cond ((null? irest)
(reverse! orest) )
((keyword? (car irest))
(loop (cddr irest) orest) )
(else
(loop (cdr irest) (cons (car irest) orest)) ) ) ) )
;; composite-entropy-source-constructor
;;
;; returns the composite name & constructor
;FIXME - the combinators are suspect
(define (composite-entropy-source-constructor
#!rest rest0
#!key
(comb-int (lambda (ints n) (modulo (reduce fx+ 0 ints) n)))
(comb-real (lambda (reals unit) (reduce fp* 1.0 reals))))
;scrub keyword arguments
(let* ((rest (pull-rest-argument rest0))
(srcs0
(if (null? rest)
(error 'composite-entropy-source-constructor "no entropy-sources to combine")
(map (cut check-entropy-source 'composite-entropy-source-constructor <>) rest))) )
;collect features
(let loop ((srcs srcs0) (names '()) (docus '()))
(if (null? srcs)
;then make composed entropy-source
(*composite-entropy-source-constructor
comb-int comb-real
(string->symbol (reverse-string-append (intersperse names "+")))
(reverse-string-append (intersperse docus " & "))
srcs0)
;else collect info
(let ((es (car srcs)))
(loop
(cdr srcs)
(cons (->string (*entropy-source-name es)) names)
(cons (*entropy-source-documentation es) docus)) ) ) ) ) )
;; *composite-entropy-source-constructor
;;
;; returns the composite constructor
(define (*composite-entropy-source-constructor comb-int comb-real def-name def-docu srcs)
(let ((u8proc
(lambda ()
(comb-int
(map (lambda (es) ((@entropy-source-u8 es))) srcs)
255) ) )
(f64proc
(lambda ()
(comb-real
(map (lambda (es) ((@entropy-source-f64 es))) srcs)
#f) ) ) )
(letrec ((ctor
(lambda (#!optional (name def-name) (docu def-docu))
(*make-entropy-source
;
ctor
;
name
;
docu
;
u8proc
;
f64proc
;
(lambda (u8cnt u8vec)
(let ((u8vec (or u8vec (make-u8vector u8cnt))))
(u8vector-filled! u8vec u8proc 0 u8cnt)
u8vec ) )
;
(lambda (f64cnt f64vec)
(let ((f64vec (or f64vec (make-f64vector f64cnt))))
(f64vector-filled! f64vec f64proc 0 f64cnt)
f64vec ) ) ) ) ) )
ctor ) ) )
) ;module composite-entropy-source