From: Andreas Rottmann <a.rottmann@gmx.at>
To: Guile Development <guile-devel@gnu.org>
Subject: [PATCH] Support for SRFI 27
Date: Sat, 14 Aug 2010 17:55:00 +0200 [thread overview]
Message-ID: <87eie1w5nv.fsf@delenn.lan> (raw)
[-- Attachment #1: Type: text/plain, Size: 70 bytes --]
Hi!
Attached is my take on adding SRFI 27 "Sources of Random Bits".
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: srfi-27-new.diff --]
[-- Type: text/x-diff, Size: 8268 bytes --]
From: Andreas Rottmann <a.rottmann@gmx.at>
Subject: Add implementation of SRFI 27
* module/srfi/srfi-27.scm: New file; implementation of SRFI 27 in terms of the
existing random number generator.
* module/Makefile.am (SRFI_SOURCES): Add srfi/srfi-27.scm.
---
NEWS | 4 ++
module/Makefile.am | 1 +
module/srfi/srfi-27.scm | 86 +++++++++++++++++++++++++++++++++++++++++
test-suite/Makefile.am | 1 +
test-suite/tests/srfi-27.test | 81 ++++++++++++++++++++++++++++++++++++++
5 files changed, 173 insertions(+), 0 deletions(-)
diff --git a/NEWS b/NEWS
index c6caed3..e4d1117 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,10 @@ latest prerelease, and a full NEWS corresponding to 1.8 -> 2.0.
Changes in 1.9.12 (since the 1.9.11 prerelease):
+** Support for SRFI-27
+
+SRFI-27 "Sources of Random Bits" is now available.
+
** Many R6RS bugfixes
`(rnrs bytevectors)' and `(rnrs io ports)' now have version information,
diff --git a/module/Makefile.am b/module/Makefile.am
index a2fb0f3..588f560 100644
--- a/module/Makefile.am
+++ b/module/Makefile.am
@@ -252,6 +252,7 @@ SRFI_SOURCES = \
srfi/srfi-18.scm \
srfi/srfi-19.scm \
srfi/srfi-26.scm \
+ srfi/srfi-27.scm \
srfi/srfi-31.scm \
srfi/srfi-34.scm \
srfi/srfi-35.scm \
diff --git a/module/srfi/srfi-27.scm b/module/srfi/srfi-27.scm
new file mode 100644
index 0000000..cb8aaf7
--- /dev/null
+++ b/module/srfi/srfi-27.scm
@@ -0,0 +1,86 @@
+;;; 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 not yet documented at all in the Guile 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))
+
+(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))))
+
+;; We ignore `unit', which should still be compliant behavior according to
+;; SRFI-27.
+(define* (random-source-make-reals s #:optional unit)
+ (lambda ()
+ (random:uniform (random-source-state 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))
diff --git a/test-suite/Makefile.am b/test-suite/Makefile.am
index eab1cd5..d9f3951 100644
--- a/test-suite/Makefile.am
+++ b/test-suite/Makefile.am
@@ -110,6 +110,7 @@ SCM_TESTS = tests/00-initial-env.test \
tests/srfi-14.test \
tests/srfi-19.test \
tests/srfi-26.test \
+ tests/srfi-27.test \
tests/srfi-31.test \
tests/srfi-34.test \
tests/srfi-35.test \
diff --git a/test-suite/tests/srfi-27.test b/test-suite/tests/srfi-27.test
new file mode 100644
index 0000000..bd1ebcc
--- /dev/null
+++ b/test-suite/tests/srfi-27.test
@@ -0,0 +1,81 @@
+;;; -*- mode: scheme; coding: utf-8; -*-
+;;;
+;;; 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 program. If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (test-srfi-27)
+ #:use-module (test-suite lib)
+ #:use-module (srfi srfi-27))
+
+(with-test-prefix "large integers"
+ (pass-if "in range"
+ (let loop ((k 0) (n 1))
+ (cond ((> k 1024)
+ #t)
+ ((<= 0 (random-integer n) (- n 1))
+ (loop (+ k 1) (* n 2)))
+ (else
+ #f)))))
+
+(with-test-prefix "reals"
+ (pass-if "in range"
+ (let loop ((k 0) (n 1))
+ (if (> k 1000)
+ #t
+ (let ((x (random-real)))
+ (if (< 0 x 1)
+ (loop (+ k 1) (* n 2))
+ #f))))))
+
+(with-test-prefix "get/set state"
+ (let* ((state1 (random-source-state-ref default-random-source))
+ (x1 (random-integer (expt 2 32)))
+ (state2 (random-source-state-ref default-random-source))
+ (x2 (random-integer (expt 2 32))))
+ (random-source-state-set! default-random-source state1)
+ (pass-if "state1"
+ (= x1 (random-integer (expt 2 32))))
+ (random-source-state-set! default-random-source state2)
+ (pass-if "state2"
+ (= x2 (random-integer (expt 2 32))))))
+
+;; These tests are commented out since it /could/ happen that
+;; `random-source-randomize!' (or `random-source-pseudo-randomize!') puts the
+;; RNG into a state where it generates the same number as before. If you run
+;; them manually, they should have a very high chance of passing, though.
+
+#;
+(with-test-prefix "randomize!"
+ (let* ((state1 (random-source-state-ref default-random-source))
+ (x1 (random-integer (expt 2 32))))
+ (random-source-state-set! default-random-source state1)
+ (random-source-randomize! default-random-source)
+ (pass-if "other number"
+ (not (= x1 (random-integer (expt 2 32)))))))
+
+#;
+(with-test-prefix "pseudo-randomize!"
+ (let* ((state1 (random-source-state-ref default-random-source))
+ (x1 (random-integer (expt 2 32))))
+ (random-source-state-set! default-random-source state1)
+ (random-source-pseudo-randomize! default-random-source 0 1)
+ (let ((y1 (random-integer (expt 2 32))))
+ (pass-if "other number (0 1)"
+ (not (= x1 y1))))
+ (random-source-state-set! default-random-source state1)
+ (random-source-pseudo-randomize! default-random-source 1 0)
+ (let ((y1 (random-integer (expt 2 32))))
+ (pass-if "other number (1 0)"
+ (not (= x1 y1))))))
--
tg: (fe3f01f..) t/srfi-27-new (depends on: t/random-external t/fix-random-64bit)
[-- Attachment #3: Type: text/plain, Size: 63 bytes --]
Regards, Rotty
--
Andreas Rottmann -- <http://rotty.yi.org/>
next reply other threads:[~2010-08-14 15:55 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-08-14 15:55 Andreas Rottmann [this message]
2010-08-15 14:57 ` [PATCH] Support for SRFI 27 Ludovic Courtès
2010-08-28 17:15 ` Andy Wingo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/guile/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87eie1w5nv.fsf@delenn.lan \
--to=a.rottmann@gmx.at \
--cc=guile-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).