Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions src/Random.elm
Original file line number Diff line number Diff line change
Expand Up @@ -678,21 +678,39 @@ type Seed
next : Seed -> Seed
next (Seed state0 incr) =
-- The magic constant is from Numerical Recipes and is inlined for perf.
Seed (Bitwise.shiftRightZfBy 0 ((state0 * 1664525) + incr)) incr
Seed (Bitwise.shiftRightZfBy 0 ((imul32 state0 1664525) + incr)) incr


-- obtain a psuedorandom 32-bit integer from a seed
-- obtain a pseudorandom 32-bit integer from a seed
peel : Seed -> Int
peel (Seed state _) =
-- This is the RXS-M-SH version of PCG, see section 6.3.4 of the paper
-- and line 184 of pcg_variants.h in the 0.94 (non-minimal) C implementation,
-- the latter of which is the source of the magic constant.
let
word =
(Bitwise.xor state (Bitwise.shiftRightZfBy ((Bitwise.shiftRightZfBy 28 state) + 4) state)) * 277803737
imul32
(Bitwise.xor state (Bitwise.shiftRightZfBy ((Bitwise.shiftRightZfBy 28 state) + 4) state))
277803737
in
Bitwise.shiftRightZfBy 0 (Bitwise.xor (Bitwise.shiftRightZfBy 22 word) word)

{-| Needed for u32 * u32 multiplications. Emulates JavaScript's Math.imul(a,b) but returns the result as an _unsigned_ 32bit number.
This would ideally live in the Bitwise module.
-}
imul32 : Int -> Int -> Int
imul32 a b =
let
aHi = Bitwise.shiftRightZfBy 16 a
aLo = Bitwise.and 0xFFFF a
bHi = Bitwise.shiftRightZfBy 16 b
bLo = Bitwise.and 0xFFFF b
low = aLo * bLo
high = Bitwise.and 0xFFFF (aHi * bLo + aLo * bHi)
in
(low + high * 0x00010000)
|> Bitwise.shiftRightZfBy 0


{-| A `Generator` is a **recipe** for generating random values. For example,
here is a generator for numbers between 1 and 10 inclusive:
Expand Down