add `pseudo-random-generator-vector?'

Also, adjust docs to clarify that `vector->pseudo-random-generator!'
can be used as a more complete seeding function.
This commit is contained in:
Matthew Flatt 2011-12-09 09:12:17 -07:00
parent 1da5b859b7
commit 287d5cedf5
7 changed files with 861 additions and 812 deletions

View File

@ -796,7 +796,13 @@ Seeds the current pseudo-random number generator with
@racket[k]. Seeding a generator sets its internal state
deterministically; that is, seeding a generator with a particular
number forces it to produce a sequence of pseudo-random numbers that
is the same across runs and across platforms.}
is the same across runs and across platforms.
The @racket[random-seed] function is convenient for some purposes, but
note that the space of states for a pseudo-random number generator is
much larger that the space of allowed values for @racket[k]. Use
@racket[vector->pseudo-random-generator!] to set a pseudo-random
number generator to any of its possible states.}
@defproc[(make-pseudo-random-generator) pseudo-random-generator?]{
@ -818,7 +824,7 @@ used by @racket[random].}
@defproc[(pseudo-random-generator->vector [generator pseudo-random-generator?])
vector?]{
pseudo-random-generator-vector?]{
Produces a vector that represents the complete internal state of
@racket[generator]. The vector is suitable as an argument to
@ -826,25 +832,30 @@ Produces a vector that represents the complete internal state of
its current state (across runs and across platforms).}
@defproc[(vector->pseudo-random-generator [vec vector?])
@defproc[(vector->pseudo-random-generator [vec pseudo-random-generator-vector?])
pseudo-random-generator?]{
Produces a pseudo-random number generator whose internal state
corresponds to @racket[vec]. The vector @racket[vec] must contain six
exact integers; the first three integers must be in the range
@racket[0] to @racket[4294967086], inclusive; the last three integers
must be in the range @racket[0] to @racket[4294944442], inclusive; at
least one of the first three integers must be non-zero; and at least
one of the last three integers must be non-zero.}
corresponds to @racket[vec].}
@defproc[(vector->pseudo-random-generator! [generator pseudo-random-generator?]
[vec vector?])
[vec pseudo-random-generator-vector?])
void?]{
Like @racket[vector->pseudo-random-generator], but changes
@racket[generator] to the given state, instead of creating a new
generator.}
@defproc[(pseudo-random-generator-vector? [v any/c]) boolean?]{
Returns @racket[#t] if @racket[v] is a vector of six exact integers,
where the first three integers are in the range @racket[0] to
@racket[4294967086], inclusive; the last three integers are in the
range @racket[0] to @racket[4294944442], inclusive; at least one of
the first three integers is non-zero; and at least one of the last
three integers is non-zero. Otherwise, the result is @racket[#f].}
@; ------------------------------------------------------------------------
@subsection{Number--String Conversions}

View File

@ -2230,6 +2230,22 @@
(arity-test current-evt-pseudo-random-generator 0 1)
(err/rt-test (current-pseudo-random-generator 10))
(let ([g (current-pseudo-random-generator)])
(test #t pseudo-random-generator-vector? (pseudo-random-generator->vector g)))
(test #f pseudo-random-generator-vector? #())
(test #t pseudo-random-generator-vector? #(1 2 3 4 5 6))
(test #f pseudo-random-generator-vector? #(0 0 0 4 5 6))
(test #f pseudo-random-generator-vector? #(1 2 3 0 0 0))
(test #f pseudo-random-generator-vector? #(1 2 3 4 5 #f))
(err/rt-test (vector->pseudo-random-generator #()))
(err/rt-test (vector->pseudo-random-generator #(0 0 0 1 2 3)))
;; Known state should produce known values:
(parameterize ([current-pseudo-random-generator
(vector->pseudo-random-generator
#(3620087466 1904163406 3177592043 1406334318 257151704 3090455638))])
(test 5353 random 10000)
(test 8571 random 10000)
(test 9729 random 10000))
(test #t = 0 0)
(test #f = 0 (expt 2 32))

View File

@ -1,3 +1,6 @@
Version 5.2.0.6
Added pseudo-random-generator-vector?
Version 5.2.0.5
Cross-module inlining of trivial functions, plus map, for-each,
andmap, and ormap; 'compiler-hint:cross-module-inline hint

File diff suppressed because it is too large Load Diff

View File

@ -28,7 +28,7 @@
the error messages are better this way.
Also, for no particularly good reason, random-number support is
here, though the real work is in random.inc (from FreeBSD). */
here, though the real work is in newrandom.inc. */
#include "schpriv.h"
#include <math.h>
@ -53,6 +53,7 @@ static Scheme_Object *pseudo_random_generator_p(int argc, Scheme_Object **argv);
static Scheme_Object *sch_unpack(int argc, Scheme_Object *argv[]);
static Scheme_Object *sch_pack(int argc, Scheme_Object *argv[]);
static Scheme_Object *sch_pack_bang(int argc, Scheme_Object *argv[]);
static Scheme_Object *sch_check_pack(int argc, Scheme_Object *argv[]);
static char *number_to_allocated_string(int radix, Scheme_Object *obj, int alloc);
@ -151,6 +152,11 @@ void scheme_init_numstr(Scheme_Env *env)
"pseudo-random-generator->vector",
1, 1),
env);
scheme_add_global_constant("pseudo-random-generator-vector?",
scheme_make_prim_w_arity(sch_check_pack,
"pseudo-random-generator-vector?",
1, 1),
env);
scheme_add_global_constant("pseudo-random-generator?",
scheme_make_prim_w_arity(pseudo_random_generator_p,
"pseudo-random-generator?",
@ -2292,7 +2298,7 @@ sch_random(int argc, Scheme_Object *argv[])
}
static Scheme_Object *
do_pack(const char *name, int argc, Scheme_Object *argv[], int set)
do_pack(const char *name, int argc, Scheme_Object *argv[], int set, int check)
{
Scheme_Object *s;
GC_CAN_IGNORE Scheme_Random_State rs;
@ -2304,11 +2310,14 @@ do_pack(const char *name, int argc, Scheme_Object *argv[], int set)
}
}
if (SCHEME_VECTORP(argv[set]))
s = pack_rand_state(argv[set], (set ? &rs : NULL));
if (SCHEME_VECTORP(argv[set]) && (SCHEME_VEC_SIZE(argv[set]) == 6))
s = pack_rand_state(argv[set], ((set || check) ? &rs : NULL));
else
s = NULL;
if (check)
return (s ? scheme_true : scheme_false);
if (!s)
scheme_wrong_type(name,
"vector of six elements, three in [0, 4294967086] and three in [0, 4294944442], "
@ -2333,13 +2342,19 @@ do_pack(const char *name, int argc, Scheme_Object *argv[], int set)
static Scheme_Object *
sch_pack(int argc, Scheme_Object *argv[])
{
return do_pack("vector->pseudo-random-generator", argc, argv, 0);
return do_pack("vector->pseudo-random-generator", argc, argv, 0, 0);
}
static Scheme_Object *
sch_pack_bang(int argc, Scheme_Object *argv[])
{
return do_pack("vector->pseudo-random-generator!", argc, argv, 1);
return do_pack("vector->pseudo-random-generator!", argc, argv, 1, 0);
}
static Scheme_Object *
sch_check_pack(int argc, Scheme_Object *argv[])
{
return do_pack("pseudo-random-generator-vector?", argc, argv, 0, 1);
}
static Scheme_Object *

View File

@ -13,7 +13,7 @@
#define USE_COMPILED_STARTUP 1
#define EXPECTED_PRIM_COUNT 1041
#define EXPECTED_PRIM_COUNT 1042
#define EXPECTED_UNSAFE_COUNT 78
#define EXPECTED_FLFXNUM_COUNT 68
#define EXPECTED_FUTURES_COUNT 11

View File

@ -13,12 +13,12 @@
consistently.)
*/
#define MZSCHEME_VERSION "5.2.0.5"
#define MZSCHEME_VERSION "5.2.0.6"
#define MZSCHEME_VERSION_X 5
#define MZSCHEME_VERSION_Y 2
#define MZSCHEME_VERSION_Z 0
#define MZSCHEME_VERSION_W 5
#define MZSCHEME_VERSION_W 6
#define MZSCHEME_VERSION_MAJOR ((MZSCHEME_VERSION_X * 100) + MZSCHEME_VERSION_Y)
#define MZSCHEME_VERSION_MINOR ((MZSCHEME_VERSION_Z * 1000) + MZSCHEME_VERSION_W)