2008-03-19 17:18:03 -04:00
|
|
|
! Copyright (C) 2008 Doug Coleman.
|
2007-09-20 18:09:08 -04:00
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
2010-12-25 19:54:45 -05:00
|
|
|
USING: accessors alien.c-types alien.data arrays assocs
|
|
|
|
byte-arrays byte-vectors combinators fry io.backend io.binary
|
|
|
|
kernel locals math math.bitwise math.constants math.functions
|
2011-10-14 21:52:41 -04:00
|
|
|
math.order math.ranges namespaces sequences sequences.private
|
2011-11-15 23:45:16 -05:00
|
|
|
sets summary system vocabs hints typed ;
|
2007-09-20 18:09:08 -04:00
|
|
|
IN: random
|
|
|
|
|
2008-04-12 22:35:07 -04:00
|
|
|
SYMBOL: system-random-generator
|
2008-03-27 07:27:36 -04:00
|
|
|
SYMBOL: secure-random-generator
|
|
|
|
SYMBOL: random-generator
|
|
|
|
|
2009-09-30 04:22:11 -04:00
|
|
|
GENERIC# seed-random 1 ( tuple seed -- tuple' )
|
2009-09-30 16:56:02 -04:00
|
|
|
GENERIC: random-32* ( tuple -- r )
|
2008-03-27 07:30:59 -04:00
|
|
|
GENERIC: random-bytes* ( n tuple -- byte-array )
|
2008-03-27 07:27:36 -04:00
|
|
|
|
|
|
|
M: object random-bytes* ( n tuple -- byte-array )
|
2009-02-02 14:43:54 -05:00
|
|
|
[ [ <byte-vector> ] keep 4 /mod ] dip
|
2011-11-15 23:45:16 -05:00
|
|
|
[ pick '[ _ random-32* int <ref> _ push-all ] times ]
|
2008-11-12 23:10:34 -05:00
|
|
|
[
|
|
|
|
over zero?
|
2011-11-15 23:45:16 -05:00
|
|
|
[ 2drop ] [ random-32* int <ref> swap head append! ] if
|
|
|
|
] bi-curry bi* B{ } like ;
|
|
|
|
|
|
|
|
HINTS: M\ object random-bytes* { fixnum object } ;
|
2008-03-27 07:27:36 -04:00
|
|
|
|
2011-10-12 01:31:21 -04:00
|
|
|
M: object random-32* ( tuple -- r ) 4 swap random-bytes* be> ;
|
2008-03-27 07:27:36 -04:00
|
|
|
|
|
|
|
ERROR: no-random-number-generator ;
|
|
|
|
|
2008-03-29 15:50:52 -04:00
|
|
|
M: no-random-number-generator summary
|
|
|
|
drop "Random number generator is not defined." ;
|
|
|
|
|
2008-03-27 07:27:36 -04:00
|
|
|
M: f random-bytes* ( n obj -- * ) no-random-number-generator ;
|
|
|
|
|
2009-09-30 16:56:02 -04:00
|
|
|
M: f random-32* ( obj -- * ) no-random-number-generator ;
|
2008-03-27 07:27:36 -04:00
|
|
|
|
2011-10-14 21:52:41 -04:00
|
|
|
: random-32 ( -- n ) random-generator get random-32* ;
|
|
|
|
|
2011-11-15 23:45:16 -05:00
|
|
|
TYPED: random-bytes ( n: fixnum -- byte-array: byte-array )
|
|
|
|
random-generator get random-bytes* ; inline
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-10-04 12:44:12 -04:00
|
|
|
<PRIVATE
|
|
|
|
|
2011-10-14 21:52:41 -04:00
|
|
|
: (random-integer) ( bits -- n required-bits )
|
|
|
|
[ random-32 32 ] dip 32 - [ dup 0 > ] [
|
|
|
|
[ 32 shift random-32 + ] [ 32 + ] [ 32 - ] tri*
|
|
|
|
] while drop ;
|
|
|
|
|
2008-10-04 12:44:12 -04:00
|
|
|
: random-integer ( n -- n' )
|
2011-10-14 21:52:41 -04:00
|
|
|
dup next-power-of-2 log2 (random-integer)
|
|
|
|
[ * ] [ 2^ /i ] bi* ;
|
2008-10-04 12:44:12 -04:00
|
|
|
|
|
|
|
PRIVATE>
|
|
|
|
|
2009-05-10 14:39:08 -04:00
|
|
|
: random-bits ( numbits -- r ) 2^ random-integer ;
|
|
|
|
|
|
|
|
: random-bits* ( numbits -- n )
|
|
|
|
1 - [ random-bits ] keep set-bit ;
|
2008-10-05 23:08:13 -04:00
|
|
|
|
2010-01-14 12:59:53 -05:00
|
|
|
GENERIC: random ( obj -- elt )
|
|
|
|
|
2010-01-14 13:48:57 -05:00
|
|
|
M: integer random [ f ] [ random-integer ] if-zero ;
|
2010-01-14 12:59:53 -05:00
|
|
|
|
|
|
|
M: sequence random
|
2008-09-06 20:13:59 -04:00
|
|
|
[ f ] [
|
2008-10-04 12:44:12 -04:00
|
|
|
[ length random-integer ] keep nth
|
2008-09-06 20:13:59 -04:00
|
|
|
] if-empty ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2011-10-14 21:52:41 -04:00
|
|
|
: randomize-n-last ( seq n -- seq )
|
|
|
|
[ dup length dup ] dip - 1 max '[ dup _ > ]
|
|
|
|
[ [ random ] [ 1 - ] bi [ pick exchange-unsafe ] keep ]
|
2009-02-17 20:19:49 -05:00
|
|
|
while drop ;
|
2008-12-18 01:15:07 -05:00
|
|
|
|
2010-02-18 18:31:52 -05:00
|
|
|
: randomize ( seq -- randomized )
|
2010-01-30 01:58:29 -05:00
|
|
|
dup length randomize-n-last ;
|
2009-09-23 13:04:06 -04:00
|
|
|
|
2010-01-30 01:58:29 -05:00
|
|
|
ERROR: too-many-samples seq n ;
|
2009-09-23 13:04:06 -04:00
|
|
|
|
|
|
|
: sample ( seq n -- seq' )
|
|
|
|
2dup [ length ] dip < [ too-many-samples ] when
|
2010-01-30 01:58:29 -05:00
|
|
|
[ [ length iota >array ] dip [ randomize-n-last ] keep tail-slice* ]
|
|
|
|
[ drop ] 2bi nths ;
|
2009-09-23 13:04:06 -04:00
|
|
|
|
2008-10-04 12:44:12 -04:00
|
|
|
: delete-random ( seq -- elt )
|
2009-10-28 00:41:57 -04:00
|
|
|
[ length random-integer ] keep [ nth ] 2keep remove-nth! drop ;
|
2008-03-19 22:41:39 -04:00
|
|
|
|
2008-03-19 17:18:03 -04:00
|
|
|
: with-random ( tuple quot -- )
|
2008-03-19 22:41:39 -04:00
|
|
|
random-generator swap with-variable ; inline
|
2008-03-28 23:10:01 -04:00
|
|
|
|
2008-04-12 22:35:07 -04:00
|
|
|
: with-system-random ( quot -- )
|
|
|
|
system-random-generator get swap with-random ; inline
|
|
|
|
|
2008-03-28 23:10:01 -04:00
|
|
|
: with-secure-random ( quot -- )
|
2008-04-12 22:35:07 -04:00
|
|
|
secure-random-generator get swap with-random ; inline
|
2008-11-06 02:30:59 -05:00
|
|
|
|
2009-05-06 14:22:53 -04:00
|
|
|
: uniform-random-float ( min max -- n )
|
2011-11-16 13:03:00 -05:00
|
|
|
4 random-bytes uint deref >float
|
|
|
|
4 random-bytes uint deref >float
|
2009-05-06 18:26:21 -04:00
|
|
|
2.0 32 ^ * +
|
|
|
|
[ over - 2.0 -64 ^ * ] dip
|
|
|
|
* + ; inline
|
2009-05-06 14:22:53 -04:00
|
|
|
|
2012-03-30 20:56:00 -04:00
|
|
|
: random-unit ( -- n )
|
|
|
|
0.0 1.0 uniform-random-float ; inline
|
|
|
|
|
2011-09-09 15:42:27 -04:00
|
|
|
: (cos-random-float) ( -- n )
|
2012-03-30 20:56:00 -04:00
|
|
|
0. 2pi uniform-random-float cos ;
|
2011-09-09 15:42:27 -04:00
|
|
|
|
|
|
|
: (log-sqrt-random-float) ( -- n )
|
2012-03-30 20:56:00 -04:00
|
|
|
random-unit log -2. * sqrt ;
|
2011-09-09 15:42:27 -04:00
|
|
|
|
2009-05-06 14:22:53 -04:00
|
|
|
: normal-random-float ( mean sigma -- n )
|
2011-09-09 15:42:27 -04:00
|
|
|
(cos-random-float) (log-sqrt-random-float) * * + ;
|
2009-05-06 14:22:53 -04:00
|
|
|
|
2012-03-30 20:33:13 -04:00
|
|
|
: lognormal-random-float ( mean sigma -- n )
|
|
|
|
normal-random-float exp ;
|
|
|
|
|
|
|
|
: exponential-random-float ( lambda -- n )
|
2012-03-30 20:56:00 -04:00
|
|
|
random-unit log neg swap / ;
|
2012-03-30 20:33:13 -04:00
|
|
|
|
|
|
|
: weibull-random-float ( lambda k -- n )
|
2012-03-30 20:56:00 -04:00
|
|
|
[ random-unit log neg ] dip 1. swap / ^ * ;
|
2012-03-30 20:33:13 -04:00
|
|
|
|
|
|
|
: pareto-random-float ( alpha -- n )
|
2012-03-30 20:56:00 -04:00
|
|
|
[ random-unit ] dip [ 1. swap / ] bi@ ^ ;
|
2012-03-30 20:33:13 -04:00
|
|
|
|
|
|
|
: beta-random-float ( alpha beta -- n )
|
2012-03-30 20:55:18 -04:00
|
|
|
[ 1. normal-random-float ] dip over zero?
|
|
|
|
[ 2drop 0 ] [ 1. normal-random-float dupd + / ] if ;
|
|
|
|
|
|
|
|
{
|
|
|
|
{ [ os windows? ] [ "random.windows" require ] }
|
|
|
|
{ [ os unix? ] [ "random.unix" require ] }
|
|
|
|
} cond
|
2012-03-30 20:33:13 -04:00
|
|
|
|
2008-11-06 02:30:59 -05:00
|
|
|
"random.mersenne-twister" require
|