2 | module System.Random.Pure.StdGen
4 | import public Data.Bits
6 | import public Data.So
12 | import public System.Random.Pure
14 | import Text.PrettyPrint.Bernardy.Core
15 | import Text.PrettyPrint.Bernardy.Interface
18 | %language ElabReflection
24 | goldenGamma : Bits64
25 | goldenGamma = 0x9e3779b97f4a7c15
27 | shiftXor : Fin 64 -> Bits64 -> Bits64
28 | shiftXor n w = w `xor` (w `shiftR` n)
30 | shiftXorMultiply : Fin 64 -> Bits64 -> Bits64 -> Bits64
31 | shiftXorMultiply n k w = shiftXor n w * k
33 | mix64, mix64v13 : Bits64 -> Bits64
34 | mix64 = shiftXor 33 . shiftXorMultiply 33 0xc4ceb9fe1a85ec53 . shiftXorMultiply 33 0xff51afd7ed558ccd
35 | mix64v13 = shiftXor 31 . shiftXorMultiply 27 0x94d049bb133111eb . shiftXorMultiply 30 0xbf58476d1ce4e5b9
37 | mixGamma : Bits64 -> Bits64
39 | let z1 = mix64v13 z0 .|. 1
40 | n = popCount $
z1 `xor` (z1 `shiftR` 1)
43 | if n >= 24 then z1 else z1 `xor` 0xaaaaaaaaaaaaaaaa
50 | data StdGen = MkStdGen Bits64 Bits64
54 | MkStdGen seed gamma == MkStdGen seed' gamma' = seed == seed' && gamma == gamma'
57 | RandomGen StdGen where
59 | next $
MkStdGen seed gamma = do
60 | let seed' = seed + gamma
61 | (MkStdGen seed' gamma, mix64 seed')
63 | split $
MkStdGen seed gamma = do
64 | let seed' = seed + gamma
65 | seed'' = seed' + gamma
66 | (MkStdGen seed'' gamma, MkStdGen (mix64 seed') (mixGamma seed''))
69 | variant v $
MkStdGen seed gamma = MkStdGen (seed + cast v) gamma
75 | showPrec d $
MkStdGen s g = showCon d "rawStdGen" $
showArg s ++ showArg g
79 | prettyPrec d $
MkStdGen s g = prettyCon d "rawStdGen" [prettyArg s, prettyArg g]
82 | extractRaw : StdGen -> (Bits64, Bits64)
83 | extractRaw $
MkStdGen seed gamma = (seed, gamma)
88 | rawStdGen : (seed, gamma : Bits64) -> (0 gammaIsOdd : So $
testBit gamma 0) => StdGen
89 | rawStdGen s g = MkStdGen s g
93 | mkStdGen : Bits64 -> StdGen
94 | mkStdGen s = MkStdGen (mix64 s) (mixGamma (s + goldenGamma))
98 | someStdGen = rawStdGen 23462 254334222987
102 | initStdGen : HasIO io => io StdGen
104 | nano <- liftIO $
toNano <$> clockTime UTC
105 | pure $
mkStdGen $
cast !time `xor` cast nano `xor` cast !getPID
107 | export %defaulthint
108 | EntropySeed : HasIO m => CanInitSeed StdGen m
109 | EntropySeed = E where [E] CanInitSeed StdGen m where initSeed = initStdGen