random is generic, better random docs, cleanups

db4
Doug Coleman 2008-10-04 11:44:12 -05:00
parent 3d92ef87fe
commit 6b3b48a106
4 changed files with 74 additions and 26 deletions

View File

@ -3,17 +3,17 @@ random.mersenne-twister sequences tools.test math.order ;
IN: random.mersenne-twister.tests
: check-random ( max -- ? )
dup >r random 0 r> between? ;
[ random 0 ] keep between? ;
[ t ] [ 100 [ drop 674 check-random ] all? ] unit-test
: make-100-randoms
[ 100 [ 100 random , ] times ] { } make ;
: randoms ( -- seq )
100 [ 100 random ] replicate ;
: test-rng ( seed quot -- )
>r <mersenne-twister> r> with-random ;
[ f ] [ 1234 [ make-100-randoms make-100-randoms = ] test-rng ] unit-test
[ f ] [ 1234 [ randoms randoms = ] test-rng ] unit-test
[ 1333075495 ] [
0 [ 1000 [ drop random-generator get random-32* drop ] each random-generator get random-32* ] test-rng

View File

@ -1,12 +1,6 @@
USING: help.markup help.syntax math ;
USING: help.markup help.syntax math kernel sequences ;
IN: random
ARTICLE: "random-numbers" "Generating random integers"
"The " { $vocab-link "random" } " vocabulary implements the ``Mersenne Twister'' pseudo-random number generator algorithm."
{ $subsection random } ;
ABOUT: "random-numbers"
HELP: seed-random
{ $values { "tuple" "a random number generator" } { "seed" "an integer between 0 and 2^32-1" } }
{ $description "Seed the random number generator." }
@ -21,8 +15,8 @@ HELP: random-bytes*
{ $description "Generates a byte-array of random bytes." } ;
HELP: random
{ $values { "seq" "a sequence" } { "elt" "a random element" } }
{ $description "Outputs a random element of the sequence. If the sequence is empty, always outputs " { $link f } "." }
{ $values { "obj" object } { "elt" "a random element" } }
{ $description "Outputs a random element of the input object. If the object is an integer, an input of zero always returns a zero, a negative integer throws an error, and positive integers yield a random integer in the interval " { $snippet "[0,n)" } ". On a sequence, an empty sequence always outputs " { $link f } " while any other sequence outputs a random element." }
{ $notes "Since integers are sequences, passing an integer " { $snippet "n" } " yields a random integer in the interval " { $snippet "[0,n)" } "." } ;
HELP: random-bytes
@ -47,4 +41,36 @@ HELP: with-secure-random
{ $values { "quot" "a quotation" } }
{ $description "Calls the quotation with the secure random generator in a dynamic variable. All random numbers will be generated using this random generator." } ;
{ with-random with-secure-random } related-words
HELP: with-system-random
{ $values { "quot" "a quotation" } }
{ $description "Calls the quotation with the system's random generator in a dynamic variable. All random numbers will be generated using this random generator." } ;
{ with-random with-secure-random with-system-random } related-words
HELP: delete-random
{ $values
{ "seq" sequence }
{ "elt" object } }
{ $description "Delete a random number from a sequence using " { $link delete-nth } " and returns the deleted object." } ;
ARTICLE: "random-protocol" "Random protocol"
"A random number generator must implement one of these two words:"
{ $subsection random-32* }
{ $subsection random-bytes* }
"Optional, to seed a random number generator:"
{ $subsection seed-random } ;
ARTICLE: "random" "Generating random integers"
"The " { $vocab-link "random" } " vocabulary contains a protocol for generating random or pseudorandom numbers. The ``Mersenne Twister'' pseudorandom number generator algorithm is the default generator stored in " { $link random-generator } "."
"Generate a random object:"
{ $subsection random }
"Combinators to change the random number generator:"
{ $subsection with-random }
{ $subsection with-system-random }
{ $subsection with-secure-random }
"Implementation:"
{ $subsection "random-protocol" }
"Deleting a random element from a sequence:"
{ $subsection delete-random } ;
ABOUT: "random"

View File

@ -1,5 +1,5 @@
USING: random sequences tools.test kernel math math.functions
sets ;
sets math.constants ;
IN: random.tests
[ 4 ] [ 4 random-bytes length ] unit-test
@ -15,3 +15,7 @@ IN: random.tests
[ t ] [ 10000 [ 0 [ drop 400 random + ] reduce ] keep / 2 * 400 10 ~ ] unit-test
[ t ] [ 1000 [ 400 random ] replicate prune length 256 > ] unit-test
[ t ] [ pi random float? ] unit-test
[ 0 ] [ 0 random ] unit-test

View File

@ -33,20 +33,38 @@ M: f random-32* ( obj -- * ) no-random-number-generator ;
random-generator get random-bytes*
] keep head ;
: random ( seq -- elt )
[ f ] [
[
length dup log2 7 + 8 /i 1+
[ random-bytes byte-array>bignum ]
[ 3 shift 2^ ] bi / * >integer
] keep nth
] if-empty ;
: delete-random ( seq -- elt )
[ length random ] keep [ nth ] 2keep delete-nth ;
GENERIC: random ( obj -- elt )
: random-bits ( n -- r ) 2^ random ;
<PRIVATE
: random-integer ( n -- n' )
dup log2 7 + 8 /i 1+
[ random-bytes byte-array>bignum ]
[ 3 shift 2^ ] bi / * >integer ;
PRIVATE>
M: sequence random ( seq -- elt )
[ f ] [
[ length random-integer ] keep nth
] if-empty ;
ERROR: negative-random n ;
M: integer random ( integer -- integer' )
{
{ [ dup 0 = ] [ ] }
{ [ dup 0 < ] [ negative-random ] }
[ random-integer ]
} cond ;
M: float random ( float -- elt )
64 random-bits 64 2^ 1- / * ;
: delete-random ( seq -- elt )
[ length random-integer ] keep [ nth ] 2keep delete-nth ;
: with-random ( tuple quot -- )
random-generator swap with-variable ; inline