1 ! Copyright (C) 2009 Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors alien.c-types kernel locals math math.ranges
4 math.bitwise math.vectors math.vectors.simd random
5 sequences specialized-arrays sequences.private classes.struct
6 combinators.short-circuit fry ;
8 SPECIALIZED-ARRAY: uint
9 SPECIALIZED-ARRAY: uint-4
14 CONSTANT: state-multiplier 1812433253
28 { uint-array uint-array }
29 { uint-4-array uint-4-array } ;
32 dup 1 hlshift vbitxor ; inline
35 [ 11 vrshift ] dip vbitand ; inline
43 : formula ( a b mask c d -- r )
46 [ wA ] dip vbitxor ; inline
48 GENERIC: generate ( sfmt -- )
50 M:: sfmt generate ( sfmt -- )
52 sfmt uint-4-array>> :> array
53 state n>> 2 - array nth state (>>r1)
54 state n>> 1 - array nth state (>>r2)
59 n m - >fixnum iota [| i |
61 i m + array nth-unsafe
62 mask state r1>> state r2>> formula :> r
64 r i array set-nth-unsafe
65 state r2>> state (>>r1)
71 n m - 1 + + >fixnum :> i
73 m n - i + array nth-unsafe
74 mask state r1>> state r2>> formula :> r
76 r i array set-nth-unsafe
77 state r2>> state (>>r1)
83 : period-certified? ( sfmt -- ? )
84 [ uint-4-array>> first ]
85 [ state>> parity>> ] bi vbitand odd-parity? ;
87 : first-set-bit ( x -- n )
89 dup { [ 0 > ] [ 1 bitand 0 = ] } 1&&
91 [ 1 + ] [ -1 shift ] bi*
94 : correct-period ( sfmt -- )
96 [ state>> parity>> first first-set-bit ]
97 [ uint-array>> swap '[ _ toggle-bit ] change-nth ] tri ;
99 : certify-period ( sfmt -- sfmt )
100 dup period-certified? [ dup correct-period ] unless ;
102 : <sfmt-array> ( sfmt -- uint-array uint-4-array )
104 [ n>> 4 * 1 swap [a,b] >uint-array ] [ seed>> ] bi
107 [ -30 shift ] [ ] bi bitxor
108 state-multiplier * 32 bits
110 ] uint-array{ } accumulate-as nip
111 dup underlying>> byte-array>uint-4-array ;
113 : <sfmt-state> ( seed n m mask parity -- sfmt )
122 : init-sfmt ( sfmt -- sfmt' )
123 dup <sfmt-array> [ >>uint-array ] [ >>uint-4-array ] bi*
124 certify-period [ generate ] keep ; inline
126 : <sfmt> ( seed n m mask parity -- sfmt )
132 : refill-sfmt? ( sfmt -- ? )
133 state>> [ index>> ] [ n>> 4 * ] bi >= ; inline
135 : next-index ( sfmt -- index )
136 state>> [ dup 1 + ] change-index drop ; inline
139 [ next-index ] [ uint-array>> ] bi nth-unsafe ; inline
143 M: sfmt random-32* ( sfmt -- n )
144 dup refill-sfmt? [ dup generate ] when next ; inline
146 M: sfmt seed-random ( sfmt seed -- sfmt )
147 [ [ state>> ] dip >>seed drop ]
148 [ drop init-sfmt ] 2bi ;
150 : <sfmt-19937> ( seed -- sfmt )
152 uint-4{ HEX: dfffffef HEX: ddfecb7f HEX: bffaffff HEX: bffffff6 }
153 uint-4{ HEX: 1 HEX: 0 HEX: 0 HEX: 13c9e684 }