]> gitweb.factorcode.org Git - factor.git/blobdiff - basis/random/random.factor
basis: use lint.vocabs tool to trim using lists
[factor.git] / basis / random / random.factor
index f425bb96e0afe24e4b4080dad1a855be2ab95883..e21a7f4d74b12bc70a406467757dd19840671b3b 100644 (file)
@@ -1,11 +1,10 @@
 ! Copyright (C) 2008 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors alien.data arrays assocs byte-arrays
-byte-vectors combinators combinators.short-circuit fry
-hashtables hashtables.private hash-sets hints io.backend
-io.binary kernel locals math math.bitwise math.constants
-math.functions math.order math.ranges namespaces sequences
-sequences.private sets summary system typed vocabs ;
+combinators combinators.short-circuit hash-sets hashtables
+hashtables.private kernel math math.bitwise math.constants
+math.functions math.order namespaces sequences sequences.private
+sets summary system vocabs ;
 QUALIFIED-WITH: alien.c-types c
 QUALIFIED-WITH: sets sets
 IN: random
@@ -14,21 +13,20 @@ SYMBOL: system-random-generator
 SYMBOL: secure-random-generator
 SYMBOL: random-generator
 
-GENERIC# seed-random 1 ( tuple seed -- tuple' )
-GENERIC: random-32* ( tuple -- r )
-GENERIC: random-bytes* ( n tuple -- byte-array )
-
-M: object random-bytes* ( n tuple -- byte-array )
-    [ [ <byte-vector> ] keep 4 /mod ] dip
-    [ pick '[ _ random-32* c:int <ref> _ push-all ] times ]
-    [
-        over zero?
-        [ 2drop ] [ random-32* c:int <ref> swap head append! ] if
-    ] bi-curry bi* B{ } like ;
-
-HINTS: M\ object random-bytes* { fixnum object } ;
+GENERIC#: seed-random 1 ( obj seed -- obj )
+GENERIC: random-32* ( obj -- n )
+GENERIC: random-bytes* ( n obj -- byte-array )
+
+M: object random-bytes*
+    [ integer>fixnum-strict [ (byte-array) ] keep ] dip
+    [ over 4 >= ] [
+        [ 4 - ] dip
+        [ random-32* 2over c:int c:set-alien-value ] keep
+    ] while over zero? [ 2drop ] [
+        random-32* c:int <ref> swap head 0 pick copy-unsafe
+    ] if ;
 
-M: object random-32* ( tuple -- r )
+M: object random-32*
     4 swap random-bytes* c:uint deref ;
 
 ERROR: no-random-number-generator ;
@@ -36,46 +34,60 @@ ERROR: no-random-number-generator ;
 M: no-random-number-generator summary
     drop "Random number generator is not defined." ;
 
-M: f random-bytes* ( n obj -- * ) no-random-number-generator ;
+M: f random-bytes* no-random-number-generator ;
 
-M: f random-32* ( obj -- * ) no-random-number-generator ;
+M: f random-32* no-random-number-generator ;
 
-: random-32 ( -- n ) random-generator get random-32* ;
+: random-32 ( -- n )
+    random-generator get random-32* ;
 
-TYPED: random-bytes ( n: fixnum -- byte-array: byte-array )
-    random-generator get random-bytes* ; inline
+: random-bytes ( n -- byte-array )
+    random-generator get random-bytes* ;
 
 <PRIVATE
 
-: #bits ( n -- bits )
+:: (random-bits) ( numbits obj -- n )
+    numbits 32 > [
+        obj random-32* numbits 32 - [ dup 32 > ] [
+            [ 32 shift obj random-32* + ] [ 32 - ] bi*
+        ] while [
+            [ shift ] keep obj random-32* swap bits +
+        ] unless-zero
+    ] [
+        obj random-32* numbits bits
+    ] if ; inline
+
+PRIVATE>
+
+: random-bits ( numbits -- n )
+    random-generator get (random-bits) ;
+
+: random-bits* ( numbits -- n )
+    1 - [ random-bits ] keep set-bit ;
+
+<PRIVATE
+
+: next-power-of-2-bits ( m -- numbits )
     dup 2 <= [ drop 1 ] [ 1 - log2 1 + ] if ; inline
 
-:: (random-bits) ( n bits obj -- n' )
-    obj random-32* 32 bits 32 - [ dup 0 > ] [
+:: random-integer-loop ( m obj -- n )
+    obj random-32* 32 m next-power-of-2-bits 32 - [ dup 0 > ] [
         [ 32 shift obj random-32* + ] [ 32 + ] [ 32 - ] tri*
-    ] while drop [ n * ] [ neg shift ] bi* ; inline
-
-: ((random-integer)) ( n obj -- n' )
-    [ dup #bits ] dip (random-bits) ; inline
+    ] while drop [ m * ] [ neg shift ] bi* ; inline
 
-GENERIC# (random-integer) 1 ( n obj -- n )
-M: fixnum (random-integer) ( n obj -- n' ) ((random-integer)) ;
-M: bignum (random-integer) ( n obj -- n' ) ((random-integer)) ;
+GENERIC#: (random-integer) 1 ( m obj -- n )
+M: fixnum (random-integer) random-integer-loop ;
+M: bignum (random-integer) random-integer-loop ;
 
-: random-integer ( n -- n' )
+: random-integer ( m -- n )
     random-generator get (random-integer) ;
 
 PRIVATE>
 
-: random-bits ( numbits -- r )
-    [ 2^ ] keep random-generator get (random-bits) ;
-
-: random-bits* ( numbits -- n )
-    1 - [ random-bits ] keep set-bit ;
-
 GENERIC: random ( obj -- elt )
 
-M: integer random [ f ] [ random-integer ] if-zero ;
+M: integer random
+    [ f ] [ random-integer ] if-zero ;
 
 M: sequence random
     [ f ] [
@@ -94,7 +106,12 @@ M: hashtable random
 
 M: sets:set random members random ;
 
-M: hash-set random table>> random first ;
+M: hash-set random
+    dup cardinality [ drop f ] [
+        [ 0 ] [ array>> ] [ random ] tri* 1 + [
+            [ 2dup array-nth tombstone? [ 1 + ] 2dip ] loop
+        ] times [ 1 - ] dip array-nth
+    ] if-zero ;
 
 : randomize-n-last ( seq n -- seq )
     [ dup length dup ] dip - 1 max '[ dup _ > ]
@@ -110,14 +127,14 @@ ERROR: too-many-samples seq n ;
 
 : sample ( seq n -- seq' )
     2dup [ length ] dip < [ too-many-samples ] when
-    [ [ length iota >array ] dip [ randomize-n-last ] keep tail-slice* ]
-    [ drop ] 2bi nths ;
+    [ [ length <iota> >array ] dip [ randomize-n-last ] keep tail-slice* ]
+    [ drop ] 2bi nths-unsafe ;
 
 : delete-random ( seq -- elt )
     [ length random-integer ] keep
     [ nth ] 2keep remove-nth! drop ;
 
-: with-random ( tuple quot -- )
+: with-random ( obj quot -- )
     random-generator swap with-variable ; inline
 
 : with-system-random ( quot -- )
@@ -157,12 +174,16 @@ PRIVATE>
 : random-integers ( length n -- sequence )
     random-generator get '[ _ _ (random-integer) ] replicate ;
 
+<PRIVATE
+
 : (cos-random-float) ( -- n )
     0. 2pi uniform-random-float cos ;
 
 : (log-sqrt-random-float) ( -- n )
     random-unit log -2. * sqrt ;
 
+PRIVATE>
+
 : normal-random-float ( mean sigma -- n )
     (cos-random-float) (log-sqrt-random-float) * * + ;
 
@@ -181,6 +202,8 @@ PRIVATE>
 : pareto-random-float ( k alpha -- n )
     [ random-unit ] dip recip ^ /f ;
 
+<PRIVATE
+
 :: (gamma-random-float>1) ( alpha beta -- n )
     ! Uses R.C.H. Cheng, "The generation of Gamma
     ! variables with non-integral shape parameters",
@@ -232,6 +255,8 @@ PRIVATE>
         ] if x!
     ] do while x beta * ;
 
+PRIVATE>
+
 : gamma-random-float ( alpha beta -- n )
     {
         { [ over 1 > ] [ (gamma-random-float>1) ] }
@@ -270,6 +295,8 @@ PRIVATE>
         rnd (random-unit) 0.5 > [ + ] [ - ] if
     ] if ;
 
+<PRIVATE
+
 :: (triangular-random-float) ( low high mode -- n )
     mode low - high low - / :> c!
     random-unit :> u!
@@ -277,6 +304,8 @@ PRIVATE>
     u c > [ 1. u - u! 1. c - c! swap ] when
     [ - u c * sqrt * ] keep + ;
 
+PRIVATE>
+
 : triangular-random-float ( low high -- n )
     2dup + 2 /f (triangular-random-float) ;