]> gitweb.factorcode.org Git - factor.git/commitdiff
random.pcg: add 32-bit implementation
authorAlexander Ilin <alex.ilin@protonmail.com>
Tue, 4 Jan 2022 21:24:23 +0000 (22:24 +0100)
committerJohn Benediktsson <mrjbq7@gmail.com>
Fri, 20 Jan 2023 22:15:14 +0000 (14:15 -0800)
extra/random/pcg/pcg.factor

index 2f9669ecac6f0006635e2254acd568f0e139f13a..2447f3848b222852aa4c64db041ea1080a7789ea 100644 (file)
@@ -1,26 +1,35 @@
 ! Copyright (C) 2022 Alexander Ilin.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors alien.c-types classes.struct kernel locals math
-math.bitwise random ;
+math.bitwise random sets system ;
 IN: random.pcg
 
-! https://github.com/tkaitchuck/Mwc256XXA64/blob/main/impl/src/gen64.rs
 ! https://www.pcg-random.org/
+! https://github.com/tkaitchuck/Mwc256XXA64/blob/main/impl/src/gen32.rs
+! https://github.com/tkaitchuck/Mwc256XXA64/blob/main/impl/src/gen64.rs
 
 ! Since we are only returning 32 bits per step of this 64-bit PRNG, the rest are
 ! saved in the rem field.
 TUPLE: Mwc256XXA64 x1 x2 x3 c rem ;
+TUPLE: Mwc128XXA32 x1 x2 x3 c ;
 
 <PRIVATE
 
 CONSTANT: MULTIPLIER 0xfeb3_4465_7c0a_f413
+CONSTANT: MULTIPLIER-32 3487286589
 
 : big>d/d ( n -- low high )
     dup -64 shift [ 64 bits ] bi@ ; inline
 
+: multiply-32 ( n -- low high )
+    MULTIPLIER-32 * d>w/w ; inline
+
 : multiply ( n -- low high )
     MULTIPLIER * big>d/d ; inline
 
+: permute-32 ( high x1 x2 x3 -- n )
+    [ bitxor ] 2bi@ w+ ; inline
+
 : permute ( high x1 x2 x3 -- n )
     [ bitxor ] 2bi@ W+ ; inline
 
@@ -31,9 +40,16 @@ CONSTANT: MULTIPLIER 0xfeb3_4465_7c0a_f413
         x1 >>x1
         c >>c ; inline
 
+: update-state-32 ( obj low high -- )
+    [ over c>> + d>w/w ] dip w+ rot-state drop ; inline
+
 : update-state ( obj low high -- )
     [ over c>> + big>d/d ] dip W+ rot-state drop ; inline
 
+: next-u32 ( obj -- n )
+    dup x3>> multiply-32 [ pick [ x1>> ] [ x2>> ] [ x3>> ] tri permute-32 ] keep
+    swap [ update-state-32 ] dip ; inline
+
 : next-u64 ( obj -- n )
     dup x3>> multiply [ pick [ x1>> ] [ x2>> ] [ x3>> ] tri permute ] keep
     swap [ update-state ] dip ; inline
@@ -45,13 +61,24 @@ CONSTANT: MULTIPLIER 0xfeb3_4465_7c0a_f413
 
 PRIVATE>
 
+: <Mwc128XXA32> ( key1 key2 -- obj )
+    0xcafef00d 0xd15ea5e5 Mwc128XXA32 boa
+    6 [ dup next-u64 drop ] times ;
+
 : <Mwc256XXA64> ( key1 key2 -- obj )
     0xcafef00dd15ea5e5 0x14057B7EF767814F f Mwc256XXA64 boa
     6 [ dup next-u64 drop ] times ;
 
+: <pcg> ( key1 key2 -- obj )
+    cpu { x86.32 ppc.32 arm.32 } in? [ <Mwc128XXA32> ] [ <Mwc256XXA64> ] if ;
+
+M: Mwc128XXA32 random-32*
+    next-u32 ;
+
 M: Mwc256XXA64 random-32*
     dup [ [ next-u64 d>w/w ] cache ] change-rem drop ;
 
 ! USING: random random.pcg random.pcg-vec ;
 ! gc 0 0 random.pcg:<Mwc256XXA64> [ 10,000,000 [ dup random-32* drop ] times ] time drop
+! gc 0 0 random.pcg:<Mwc128XXA32> [ 10,000,000 [ dup random-32* drop ] times ] time drop
 ! gc 0 0 random.pcg-vec:<Mwc256XXA64> [ 10,000,000 [ dup random-32* drop ] times ] time drop