add flrandom and unsafe-flrandom

This commit is contained in:
Matthew Flatt 2013-11-12 20:16:00 -07:00
parent 7d2b085baa
commit 6e983482bb
16 changed files with 1429 additions and 1338 deletions

View File

@ -131,6 +131,10 @@ Like @racket[make-rectangular], @racket[real-part], and
@racket[imag-part], but both parts of the complex number must be @racket[imag-part], but both parts of the complex number must be
inexact.} inexact.}
@defproc[(flrandom [rand-gen pseudo-random-generator?]) (and flonum? (>/c 0) (</c 1))]{
Equivalent to @racket[(random rand-gen)].}
@; ------------------------------------------------------------------------ @; ------------------------------------------------------------------------
@section[#:tag "flvectors"]{Flonum Vectors} @section[#:tag "flvectors"]{Flonum Vectors}

View File

@ -834,10 +834,10 @@ both in binary and as integers.
@subsection{Random Numbers} @subsection{Random Numbers}
@defproc*[([(random [k (integer-in 1 4294967087)] @defproc*[([(random [k (integer-in 1 4294967087)]
[generator pseudo-random-generator? [rand-gen pseudo-random-generator?
(current-pseudo-random-generator)]) (current-pseudo-random-generator)])
exact-nonnegative-integer?] exact-nonnegative-integer?]
[(random [generator pseudo-random-generator? [(random [rand-gen pseudo-random-generator?
(current-pseudo-random-generator)]) (current-pseudo-random-generator)])
(and/c real? inexact? (>/c 0) (</c 1))])]{ (and/c real? inexact? (>/c 0) (</c 1))])]{
@ -882,17 +882,17 @@ Returns @racket[#t] if @racket[v] is a pseudo-random number generator,
@racket[#f] otherwise.} @racket[#f] otherwise.}
@defparam[current-pseudo-random-generator generator pseudo-random-generator?]{ @defparam[current-pseudo-random-generator rand-gen pseudo-random-generator?]{
A @tech{parameter} that determines the pseudo-random number generator A @tech{parameter} that determines the pseudo-random number generator
used by @racket[random].} used by @racket[random].}
@defproc[(pseudo-random-generator->vector [generator pseudo-random-generator?]) @defproc[(pseudo-random-generator->vector [rand-gen pseudo-random-generator?])
pseudo-random-generator-vector?]{ pseudo-random-generator-vector?]{
Produces a vector that represents the complete internal state of Produces a vector that represents the complete internal state of
@racket[generator]. The vector is suitable as an argument to @racket[rand-gen]. The vector is suitable as an argument to
@racket[vector->pseudo-random-generator] to recreate the generator in @racket[vector->pseudo-random-generator] to recreate the generator in
its current state (across runs and across platforms).} its current state (across runs and across platforms).}
@ -903,12 +903,12 @@ its current state (across runs and across platforms).}
Produces a pseudo-random number generator whose internal state Produces a pseudo-random number generator whose internal state
corresponds to @racket[vec].} corresponds to @racket[vec].}
@defproc[(vector->pseudo-random-generator! [generator pseudo-random-generator?] @defproc[(vector->pseudo-random-generator! [rand-gen pseudo-random-generator?]
[vec pseudo-random-generator-vector?]) [vec pseudo-random-generator-vector?])
void?]{ void?]{
Like @racket[vector->pseudo-random-generator], but changes Like @racket[vector->pseudo-random-generator], but changes
@racket[generator] to the given state, instead of creating a new @racket[rand-gen] to the given state, instead of creating a new
generator.} generator.}

View File

@ -177,6 +177,11 @@ These are similar to the safe bindings @racket[->fl] and @racket[fl->exact-integ
but further constrained to consume or produce a fixnum. but further constrained to consume or produce a fixnum.
} }
@defproc[(unsafe-flrandom [rand-gen pseudo-random-generator?]) (and flonum? (>/c 0) (</c 1))]{
Unchecked version of @racket[flrandom].
}
@section{Unsafe Data Extraction} @section{Unsafe Data Extraction}

View File

@ -164,6 +164,20 @@
(err/rt-test (for/flvector #:length 5 #:fill 0 ([i 5]) 8.0)) (err/rt-test (for/flvector #:length 5 #:fill 0 ([i 5]) 8.0))
(err/rt-test (for/flvector #:length 10 #:fill 0 ([i 5]) 8.0)) (err/rt-test (for/flvector #:length 10 #:fill 0 ([i 5]) 8.0))
;; ----------------------------------------
;; flrandom
(let ([r (make-pseudo-random-generator)]
[seed (random 100000)])
(define (reset)
(parameterize ([current-pseudo-random-generator r])
(random-seed seed)))
(test (begin (reset) (random r))
flrandom
(begin (reset) r)))
(err/rt-test (flrandom 5.0))
;; ---------------------------------------- ;; ----------------------------------------
;; Check corners of `flexpt': ;; Check corners of `flexpt':
;; Tests by Neil T.: ;; Tests by Neil T.:

View File

@ -52,10 +52,15 @@
(test result (compose post (eval `(lambda () (,proc ',x ',y)))))) (test result (compose post (eval `(lambda () (,proc ',x ',y))))))
(pre) (pre)
(test result (compose post (eval `(lambda (x) (,proc x ',y)))) x)) (test result (compose post (eval `(lambda (x) (,proc x ',y)))) x))
(define (test-un result proc x) (define (test-un result proc x
(test result (eval proc) x) #:pre [pre void]
(test result (eval `(lambda (x) (,proc x))) x) #:post [post (lambda (x) x)])
(test result (eval `(lambda () (,proc ',x))))) (pre)
(test result (compose post (eval proc)) x)
(pre)
(test result (compose post (eval `(lambda (x) (,proc x)))) x)
(pre)
(test result (compose post (eval `(lambda () (,proc ',x))))))
(test-bin 3 'unsafe-fx+ 1 2) (test-bin 3 'unsafe-fx+ 1 2)
(test-bin -1 'unsafe-fx+ 1 -2) (test-bin -1 'unsafe-fx+ 1 -2)
@ -283,6 +288,16 @@
(unsafe-extfl- (unsafe-extfl+ x y) NO-SUCH-VARIABLE))) (unsafe-extfl- (unsafe-extfl+ x y) NO-SUCH-VARIABLE)))
1.1t0 3.3t0 5.2t0)) 1.1t0 3.3t0 5.2t0))
(let ([r (make-pseudo-random-generator)]
[seed (random 100000)])
(define (reset)
(parameterize ([current-pseudo-random-generator r])
(random-seed seed)))
(reset)
(define val (random r))
(test-un val 'unsafe-flrandom r
#:pre reset))
(test-un 5 'unsafe-car (cons 5 9)) (test-un 5 'unsafe-car (cons 5 9))
(test-un 9 'unsafe-cdr (cons 5 9)) (test-un 9 'unsafe-cdr (cons 5 9))
(test-un 15 'unsafe-mcar (mcons 15 19)) (test-un 15 'unsafe-mcar (mcons 15 19))

View File

@ -1,3 +1,6 @@
Version 5.90.0.11
Added flrandom and unsafe-flrandom
Version 5.90.0.10 Version 5.90.0.10
Changed serializable-struct, etc. to provide deserialized-info:... Changed serializable-struct, etc. to provide deserialized-info:...
through a derialized-info submodule through a derialized-info submodule

View File

@ -9,6 +9,7 @@
flabs flsqrt flexp fllog flabs flsqrt flexp fllog
flsin flcos fltan flasin flacos flatan flsin flcos fltan flasin flacos flatan
flfloor flceiling flround fltruncate flexpt flfloor flceiling flround fltruncate flexpt
flrandom
fl= fl< fl<= fl> fl>= flmin flmax fl= fl< fl<= fl> fl>= flmin flmax
->fl fl->exact-integer ->fl fl->exact-integer
flvector? flvector make-flvector flvector? flvector make-flvector
@ -28,3 +29,10 @@
for*/flvector for*/flvector
flvector-copy flvector-copy
0.0) 0.0)
(define (flrandom r)
(if (pseudo-random-generator? r)
(unsafe-flrandom r)
(raise-argument-error 'flrandom
"pseudo-random-generator?"
r)))

File diff suppressed because it is too large Load Diff

View File

@ -302,7 +302,8 @@ int scheme_can_unbox_directly(Scheme_Object *obj, int extfl)
&& (SCHEME_PRIM_PROC_OPT_FLAGS(app->rator) & SCHEME_PRIM_IS_UNARY_INLINED)) { && (SCHEME_PRIM_PROC_OPT_FLAGS(app->rator) & SCHEME_PRIM_IS_UNARY_INLINED)) {
if (!extfl) { if (!extfl) {
if (IS_NAMED_PRIM(app->rator, "->fl") if (IS_NAMED_PRIM(app->rator, "->fl")
|| IS_NAMED_PRIM(app->rator, "fx->fl")) || IS_NAMED_PRIM(app->rator, "fx->fl")
|| IS_NAMED_PRIM(app->rator, "unsafe-flrandom"))
return 1; return 1;
} }
#ifdef MZ_LONG_DOUBLE #ifdef MZ_LONG_DOUBLE

View File

@ -49,6 +49,10 @@ static Scheme_Object *ts_scheme_make_fsemaphore(int argc, Scheme_Object **argv)
# define ts_scheme_make_fsemaphore scheme_make_fsemaphore # define ts_scheme_make_fsemaphore scheme_make_fsemaphore
#endif #endif
static void call_flrandom(Scheme_Object *rs) {
scheme_jit_save_fp = scheme_double_random(rs);
}
static Scheme_Object *extract_one_cc_mark_to_tag(Scheme_Object *mark_set, static Scheme_Object *extract_one_cc_mark_to_tag(Scheme_Object *mark_set,
Scheme_Object *key, Scheme_Object *key,
Scheme_Object *prompt_tag) Scheme_Object *prompt_tag)
@ -1663,6 +1667,36 @@ int scheme_generate_inlined_unary(mz_jit_state *jitter, Scheme_App2_Rec *app, in
if (jitter->unbox) if (jitter->unbox)
scheme_generate_unboxing(jitter, dest); scheme_generate_unboxing(jitter, dest);
return 1;
} else if (IS_NAMED_PRIM(rator, "unsafe-flrandom")) {
mz_jit_unbox_state ubs;
LOG_IT(("inlined %s\n", name));
mz_runstack_skipped(jitter, 1);
scheme_mz_unbox_save(jitter, &ubs);
scheme_generate_non_tail(app->rand, jitter, 0, 1, 0);
CHECK_LIMIT();
scheme_mz_unbox_restore(jitter, &ubs);
mz_runstack_unskipped(jitter, 1);
mz_prepare(1);
jit_pusharg_p(JIT_R0);
(void)mz_finish(call_flrandom);
(void)mz_tl_ldi_d_fppush(JIT_FPR0, tl_scheme_jit_save_fp, JIT_R2);
CHECK_LIMIT();
if (jitter->unbox) {
jitter->unbox_depth++;
} else {
scheme_generate_alloc_double(jitter, 0, dest);
CHECK_LIMIT();
}
return 1; return 1;
} else if (IS_NAMED_PRIM(rator, "add1")) { } else if (IS_NAMED_PRIM(rator, "add1")) {
scheme_generate_arith(jitter, rator, app->rand, NULL, 1, ARITH_ADD, 0, 1, NULL, 1, 0, 0, NULL, dest); scheme_generate_arith(jitter, rator, app->rand, NULL, 1, ARITH_ADD, 0, 1, NULL, 1, 0, 0, NULL, dest);

View File

@ -42,7 +42,7 @@
/* the actual generator */ /* the actual generator */
static double mrg32k3a(Scheme_Random_State *s) { /* (double), in {0..m1-1} */ XFORM_NONGCING static double mrg32k3a(Scheme_Random_State *s) { /* (double), in {0..m1-1} */
double x10, x20, y; double x10, x20, y;
intptr_t k10, k20; intptr_t k10, k20;
@ -212,7 +212,7 @@ static uintptr_t sch_int_rand(uintptr_t n, Scheme_Random_State *rs)
return (uintptr_t)xq; return (uintptr_t)xq;
} }
static double sch_double_rand(Scheme_Random_State *rs) XFORM_NONGCING static double sch_double_rand(Scheme_Random_State *rs)
{ {
double x; double x;
x = mrg32k3a(rs); x = mrg32k3a(rs);

View File

@ -204,6 +204,8 @@ static Scheme_Object *unsafe_make_flrectangular (int argc, Scheme_Object *argv[]
static Scheme_Object *unsafe_flreal_part (int argc, Scheme_Object *argv[]); static Scheme_Object *unsafe_flreal_part (int argc, Scheme_Object *argv[]);
static Scheme_Object *unsafe_flimag_part (int argc, Scheme_Object *argv[]); static Scheme_Object *unsafe_flimag_part (int argc, Scheme_Object *argv[]);
static Scheme_Object *unsafe_flrandom (int argc, Scheme_Object *argv[]);
#ifdef MZ_USE_SINGLE_FLOATS #ifdef MZ_USE_SINGLE_FLOATS
static Scheme_Object *TO_FLOAT(const Scheme_Object *n); static Scheme_Object *TO_FLOAT(const Scheme_Object *n);
#endif #endif
@ -1438,6 +1440,15 @@ void scheme_init_unsafe_number(Scheme_Env *env)
| SCHEME_PRIM_IS_UNSAFE_FUNCTIONAL | SCHEME_PRIM_IS_UNSAFE_FUNCTIONAL
| SCHEME_PRIM_PRODUCES_FLONUM); | SCHEME_PRIM_PRODUCES_FLONUM);
scheme_add_global_constant("unsafe-flimag-part", p, env); scheme_add_global_constant("unsafe-flimag-part", p, env);
p = scheme_make_immed_prim(unsafe_flrandom, "unsafe-flrandom", 1, 1);
if (scheme_can_inline_fp_op())
flags = SCHEME_PRIM_IS_UNARY_INLINED;
else
flags = SCHEME_PRIM_SOMETIMES_INLINED;
SCHEME_PRIM_PROC_FLAGS(p) |= scheme_intern_prim_opt_flags(flags
| SCHEME_PRIM_PRODUCES_FLONUM);
scheme_add_global_constant("unsafe-flrandom", p, env);
} }
void scheme_init_extfl_unsafe_number(Scheme_Env *env) void scheme_init_extfl_unsafe_number(Scheme_Env *env)
@ -5397,6 +5408,11 @@ static Scheme_Object *unsafe_flimag_part (int argc, Scheme_Object *argv[])
return ((Scheme_Complex *)argv[0])->i; return ((Scheme_Complex *)argv[0])->i;
} }
static Scheme_Object *unsafe_flrandom (int argc, Scheme_Object *argv[])
{
return scheme_make_double(scheme_double_random(argv[0]));
}
static Scheme_Object *integer_to_extfl (int argc, Scheme_Object *argv[]) static Scheme_Object *integer_to_extfl (int argc, Scheme_Object *argv[])
{ {
#ifdef MZ_LONG_DOUBLE #ifdef MZ_LONG_DOUBLE

View File

@ -2756,6 +2756,11 @@ sch_random(int argc, Scheme_Object *argv[])
} }
} }
double scheme_double_random(Scheme_Object *rand_state)
{
return sch_double_rand((Scheme_Random_State *)rand_state);
}
static Scheme_Object * static Scheme_Object *
do_pack(const char *name, int argc, Scheme_Object *argv[], int set, int check) do_pack(const char *name, int argc, Scheme_Object *argv[], int set, int check)
{ {

View File

@ -15,7 +15,7 @@
#define USE_COMPILED_STARTUP 1 #define USE_COMPILED_STARTUP 1
#define EXPECTED_PRIM_COUNT 1116 #define EXPECTED_PRIM_COUNT 1116
#define EXPECTED_UNSAFE_COUNT 100 #define EXPECTED_UNSAFE_COUNT 101
#define EXPECTED_FLFXNUM_COUNT 69 #define EXPECTED_FLFXNUM_COUNT 69
#define EXPECTED_EXTFL_COUNT 45 #define EXPECTED_EXTFL_COUNT 45
#define EXPECTED_FUTURES_COUNT 15 #define EXPECTED_FUTURES_COUNT 15

View File

@ -2177,6 +2177,8 @@ extern Scheme_Object *scheme_zerof, *scheme_nzerof, *scheme_single_scheme_pi;
extern Scheme_Object *scheme_single_inf_object, *scheme_single_minus_inf_object, *scheme_single_nan_object; extern Scheme_Object *scheme_single_inf_object, *scheme_single_minus_inf_object, *scheme_single_nan_object;
#endif #endif
XFORM_NONGCING double scheme_double_random(Scheme_Object *rand_state);
/****** General numeric ******/ /****** General numeric ******/
Scheme_Object *scheme_read_number(const mzchar *str, intptr_t len, Scheme_Object *scheme_read_number(const mzchar *str, intptr_t len,

View File

@ -13,12 +13,12 @@
consistently.) consistently.)
*/ */
#define MZSCHEME_VERSION "5.90.0.10" #define MZSCHEME_VERSION "5.90.0.11"
#define MZSCHEME_VERSION_X 5 #define MZSCHEME_VERSION_X 5
#define MZSCHEME_VERSION_Y 90 #define MZSCHEME_VERSION_Y 90
#define MZSCHEME_VERSION_Z 0 #define MZSCHEME_VERSION_Z 0
#define MZSCHEME_VERSION_W 10 #define MZSCHEME_VERSION_W 11
#define MZSCHEME_VERSION_MAJOR ((MZSCHEME_VERSION_X * 100) + MZSCHEME_VERSION_Y) #define MZSCHEME_VERSION_MAJOR ((MZSCHEME_VERSION_X * 100) + MZSCHEME_VERSION_Y)
#define MZSCHEME_VERSION_MINOR ((MZSCHEME_VERSION_Z * 1000) + MZSCHEME_VERSION_W) #define MZSCHEME_VERSION_MINOR ((MZSCHEME_VERSION_Z * 1000) + MZSCHEME_VERSION_W)