From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Andreas Rottmann Newsgroups: gmane.lisp.guile.devel Subject: [PATCH] Allow exposing of random number generator state Date: Sun, 18 Jul 2010 18:01:26 +0200 Message-ID: <87eif0hj8p.fsf@delenn.lan> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: dough.gmane.org 1279469103 30256 80.91.229.12 (18 Jul 2010 16:05:03 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Sun, 18 Jul 2010 16:05:03 +0000 (UTC) To: Guile Development Original-X-From: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Sun Jul 18 18:05:02 2010 Return-path: Envelope-to: guile-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1OaWMN-0007cN-5D for guile-devel@m.gmane.org; Sun, 18 Jul 2010 18:04:59 +0200 Original-Received: from localhost ([127.0.0.1]:54265 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OaWMM-0008Jv-CK for guile-devel@m.gmane.org; Sun, 18 Jul 2010 12:04:58 -0400 Original-Received: from [140.186.70.92] (port=34726 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OaWJ9-0006q3-1F for guile-devel@gnu.org; Sun, 18 Jul 2010 12:01:40 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OaWJ6-0000qL-6d for guile-devel@gnu.org; Sun, 18 Jul 2010 12:01:38 -0400 Original-Received: from mail.gmx.net ([213.165.64.20]:46759) by eggs.gnu.org with smtp (Exim 4.69) (envelope-from ) id 1OaWJ5-0000q0-Kc for guile-devel@gnu.org; Sun, 18 Jul 2010 12:01:36 -0400 Original-Received: (qmail invoked by alias); 18 Jul 2010 16:01:33 -0000 Original-Received: from 83-215-154-5.hage.dyn.salzburg-online.at (EHLO nathot.lan) [83.215.154.5] by mail.gmx.net (mp037) with SMTP; 18 Jul 2010 18:01:33 +0200 X-Authenticated: #3102804 X-Provags-ID: V01U2FsdGVkX19W6HoOoN5WoDm7ts1NLj85aFwYeZ/Ism//XDmuAf TqOL7fsadEdNOA Original-Received: from localhost (localhost.localdomain [127.0.0.1]) by nathot.lan (Postfix) with ESMTP id BFBED3A6A5 for ; Sun, 18 Jul 2010 18:01:32 +0200 (CEST) Original-Received: from nathot.lan ([127.0.0.1]) by localhost (nathot.lan [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id GhDNLJ6CZ00z for ; Sun, 18 Jul 2010 18:01:27 +0200 (CEST) Original-Received: from delenn.lan (delenn.lan [192.168.3.11]) by nathot.lan (Postfix) with ESMTP id EDC503A6A1 for ; Sun, 18 Jul 2010 18:01:26 +0200 (CEST) Original-Received: by delenn.lan (Postfix, from userid 1000) id BB32C75972; Sun, 18 Jul 2010 18:01:26 +0200 (CEST) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux) X-Y-GMX-Trusted: 0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Developers list for Guile, the GNU extensibility library" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Errors-To: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.lisp.guile.devel:10690 Archived-At: --=-=-= Hi! Here is a first version of the patch to add an external representation for the RNG state (needed for implementing SRFI 27 "Sources of random bits" in terms of Guile's RNG). I'm not quite sure about the naming of procedures, both one the C and the Scheme side of things -- suggestions highly appreciated! --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=random-external.diff From: Andreas Rottmann Subject: Allow exposing of random number generator state Now the random number generator state can be obtained in external (i.e. `read'/`write'-able) form via the new procedure `random-state->external'. An externalized state can be reinstantiated by calling `external->random-state'. * libguile/random.c (scm_i_init_rstate_scm, scm_i_expose_rstate): New internal functions. * libguile/random.c (scm_c_make_rstate_scm, scm_external_to_random_state, scm_random_state_to_external): New public functions. * libguile/random.h: Add prototypes for the above functions. * libguile/random.h (scm_t_rng): Add new fields `init_rstate_scm' and `expose_rstate'. * libguile/random.c (scm_init_random): Initialize the new fields in `scm_the_rng'. --- NEWS | 10 +++++++ doc/ref/api-data.texi | 26 +++++++++++++++-- libguile/random.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++--- libguile/random.h | 7 ++++- 4 files changed, 107 insertions(+), 8 deletions(-) diff --git a/NEWS b/NEWS index 1939a2b..80e295d 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,16 @@ Please send Guile bug reports to bug-guile@gnu.org. (During the 1.9 series, we will keep an incremental NEWS for the latest prerelease, and a full NEWS corresponding to 1.8 -> 2.0.) +Changes in 1.9.12 (since the 1.9.11 prerelease): + +** Random generator state has an external form + +Now the random number generator state can be obtained in external +(i.e. `read'/`write'-able) form via the new procedure +`random-state->external'. An externalized state can be reinstantiated by +calling `external->random-state'. + + Changes in 1.9.11 (since the 1.9.10 prerelease): ** Renamed module: (rnrs bytevectors) diff --git a/doc/ref/api-data.texi b/doc/ref/api-data.texi index 40bd969..184c4d3 100755 --- a/doc/ref/api-data.texi +++ b/doc/ref/api-data.texi @@ -1511,9 +1511,13 @@ through @var{end} (exclusive) bits of @var{n}. The @subsubsection Random Number Generation Pseudo-random numbers are generated from a random state object, which -can be created with @code{seed->random-state}. The @var{state} -parameter to the various functions below is optional, it defaults to -the state object in the @code{*random-state*} variable. +can be created with @code{seed->random-state} or +@code{external->random-state}. An external representation (i.e. one +which can written with @code{write} and read with @code{read}) of a +random state object can be obtained via +@code{random-state->external}. The @var{state} parameter to the +various functions below is optional, it defaults to the state object +in the @code{*random-state*} variable. @deffn {Scheme Procedure} copy-random-state [state] @deffnx {C Function} scm_copy_random_state (state) @@ -1582,6 +1586,22 @@ Return a uniformly distributed inexact real random number in Return a new random state using @var{seed}. @end deffn +@deffn {Scheme Procedure} external->random-state external +@deffnx {C Function} scm_external_to_random_state (external) +Return a new random state from the external representation +@var{external}, which must have been obtained by +@code{random-state->external}. +@end deffn + +@deffn {Scheme Procedure} random-state->external state +@deffnx {C Function} scm_random_state_to_external (state) +Return an external representation of @var{state}. You cannot make +any assumtions on the structure of the returned object besides that +it will be an acceptable argument to @code{external->random-state} +and that it will be able to be written and read back by the Scheme +reader. +@end deffn + @defvar *random-state* The global random state used by the above functions when the @var{state} parameter is not given. diff --git a/libguile/random.c b/libguile/random.c index 281d43a..c8ad64e 100644 --- a/libguile/random.c +++ b/libguile/random.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1999,2000,2001, 2003, 2005, 2006, 2009 Free Software Foundation, Inc. +/* Copyright (C) 1999,2000,2001, 2003, 2005, 2006, 2009, 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 @@ -151,6 +151,35 @@ scm_i_copy_rstate (scm_t_i_rstate *state) return memcpy (new_state, state, scm_the_rng.rstate_size); } +SCM_SYMBOL(scm_i_rstate_tag, "multiply-with-carry"); + +void +scm_i_init_rstate_scm (scm_t_i_rstate *state, SCM value) +#define FUNC_NAME "scm_i_init_rstate_scm" +{ + unsigned long w, c; + long length; + + SCM_VALIDATE_LIST_COPYLEN (SCM_ARG1, value, length); + SCM_ASSERT (length == 3, value, SCM_ARG1, FUNC_NAME); + SCM_ASSERT (scm_is_eq (SCM_CAR (value), scm_i_rstate_tag), + value, SCM_ARG1, FUNC_NAME); + SCM_VALIDATE_ULONG_COPY (SCM_ARG1, SCM_CADR (value), w); + SCM_VALIDATE_ULONG_COPY (SCM_ARG1, SCM_CADDR (value), c); + + state->w = w; + state->c = c; +} +#undef FUNC_NAME + +SCM +scm_i_expose_rstate (scm_t_i_rstate *state) +{ + return scm_list_3 (scm_i_rstate_tag, + scm_from_ulong (state->w), + scm_from_ulong (state->c)); +} + /* * Random number library functions @@ -168,6 +197,17 @@ scm_c_make_rstate (const char *seed, int n) return state; } +scm_t_rstate * +scm_c_make_rstate_scm (SCM external) +{ + scm_t_rstate *state; + + state = scm_gc_malloc_pointerless (scm_the_rng.rstate_size, + "random-state"); + state->reserved0 = 0; + scm_the_rng.init_rstate_scm (state, external); + return state; +} scm_t_rstate * scm_c_default_rstate () @@ -394,6 +434,28 @@ SCM_DEFINE (scm_seed_to_random_state, "seed->random-state", 1, 0, 0, } #undef FUNC_NAME +SCM_DEFINE (scm_external_to_random_state, "external->random-state", 1, 0, 0, + (SCM external), + "Return a new random state using @var{external}.\n" + "\n" + "@var{external} must be an external state representation obtained\n" + "from @code{random-state->external}.") +#define FUNC_NAME s_scm_external_to_random_state +{ + return make_rstate (scm_c_make_rstate_scm (external)); +} +#undef FUNC_NAME + +SCM_DEFINE (scm_random_state_to_external, "random-state->external", 1, 0, 0, + (SCM state), + "Return an external representation of @var{state}.") +#define FUNC_NAME s_scm_random_state_to_external +{ + SCM_VALIDATE_RSTATE (1, state); + return scm_the_rng.expose_rstate (SCM_RSTATE (state)); +} +#undef FUNC_NAME + SCM_DEFINE (scm_random_uniform, "random:uniform", 0, 1, 0, (SCM state), "Return a uniformly distributed inexact real random number in\n" @@ -590,9 +652,11 @@ scm_init_random () scm_t_rng rng = { sizeof (scm_t_i_rstate), - (unsigned long (*)()) scm_i_uniform32, - (void (*)()) scm_i_init_rstate, - (scm_t_rstate *(*)()) scm_i_copy_rstate + (unsigned long (*)()) scm_i_uniform32, + (void (*)()) scm_i_init_rstate, + (scm_t_rstate *(*)()) scm_i_copy_rstate, + (void (*)(scm_t_rstate *, SCM)) scm_i_init_rstate_scm, + (SCM (*)(scm_t_rstate *)) scm_i_expose_rstate }; scm_the_rng = rng; diff --git a/libguile/random.h b/libguile/random.h index 6cf404f..402c3f1 100644 --- a/libguile/random.h +++ b/libguile/random.h @@ -3,7 +3,7 @@ #ifndef SCM_RANDOM_H #define SCM_RANDOM_H -/* Copyright (C) 1999,2000,2001, 2006, 2008 Free Software Foundation, Inc. +/* Copyright (C) 1999,2000,2001, 2006, 2008, 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 @@ -49,6 +49,8 @@ typedef struct scm_t_rng { unsigned long (*random_bits) (scm_t_rstate *state); /* gives 32 random bits */ void (*init_rstate) (scm_t_rstate *state, const char *seed, int n); scm_t_rstate *(*copy_rstate) (scm_t_rstate *state); + void (*init_rstate_scm) (scm_t_rstate *state, SCM exposed); + SCM (*expose_rstate) (scm_t_rstate *state); } scm_t_rng; SCM_API scm_t_rng scm_the_rng; @@ -66,12 +68,15 @@ typedef struct scm_t_i_rstate { SCM_INTERNAL unsigned long scm_i_uniform32 (scm_t_i_rstate *); SCM_INTERNAL void scm_i_init_rstate (scm_t_i_rstate *, const char *seed, int n); SCM_INTERNAL scm_t_i_rstate *scm_i_copy_rstate (scm_t_i_rstate *); +SCM_INTERNAL void scm_i_init_rstate_scm (scm_t_i_rstate *state, SCM value); +SCM_INTERNAL SCM scm_i_expose_rstate (scm_t_i_rstate *state); /* * Random number library functions */ SCM_API scm_t_rstate *scm_c_make_rstate (const char *, int); +SCM_API scm_t_rstate *scm_c_make_rstate_scm (SCM external); SCM_API scm_t_rstate *scm_c_default_rstate (void); #define scm_c_uniform32(RSTATE) scm_the_rng.random_bits (RSTATE) SCM_API double scm_c_uniform01 (scm_t_rstate *); -- tg: (3fdc1d0..) t/random-external (depends on: master) --=-=-= Regards, Rotty -- Andreas Rottmann -- --=-=-=--