{-# LANGUAGE MagicHash #-}
{-# LANGUAGE StrictData #-}
module Random.XorshiftPlus
(
XorshiftPlus
, genXorshiftPlusWord
, genXorshiftPlusInt
, getWord
, getInt
, getDouble
, XorshiftPlusST
, genXorshiftPlusWordST
, getWordST
, splitMix64Next
) where
import Data.STRef
import Control.Monad.ST
import GHC.Types
import GHC.Prim
import Prelude hiding (not)
data XorshiftPlus1 = XorshiftPlus1 Word# Word#
newtype XorshiftPlusST s = XorshiftPlusST (STRef s XorshiftPlus1)
type XorshiftPlus = XorshiftPlusST RealWorld
plus :: Word# -> Word# -> Word#
plus = plusWord#
times :: Word# -> Word# -> Word#
times = timesWord#
xor :: Word# -> Word# -> Word#
xor = xor#
shiftL :: Word# -> Int# -> Word#
shiftL = uncheckedShiftL#
shiftR :: Word# -> Int# -> Word#
shiftR = uncheckedShiftRL#
splitMix64Next :: Word# -> Word#
splitMix64Next x =
let z1 = x `plus` 0x9e3779b97f4a7c15## in
let z2 = (z1 `xor` (z1 `shiftR` 30#)) `times` 0xbf58476d1ce4e5b9## in
let z3 = (z2 `xor` (z2 `shiftR` 27#)) `times` 0x94d049bb133111eb## in
z3 `xor` (z3 `shiftR` 31#)
genXorshiftPlusWordST :: Word -> ST s (XorshiftPlusST s)
genXorshiftPlusWordST (W# w) = do
ref <- newSTRef (XorshiftPlus1 w (splitMix64Next w))
return $ XorshiftPlusST ref
genXorshiftPlusWord
:: Word
-> IO XorshiftPlus
genXorshiftPlusWord w = stToIO (genXorshiftPlusWordST w)
genXorshiftPlusInt
:: Int
-> IO XorshiftPlus
genXorshiftPlusInt i = genXorshiftPlusWord (fromIntegral i)
getWordST :: XorshiftPlusST s -> ST s Word
getWordST (XorshiftPlusST ref) = do
XorshiftPlus1 w0 w1 <- readSTRef ref
let x = w0 `xor` (w0 `shiftL` 17#)
let y = x `xor` w1 `xor` (x `shiftR` 17#) `xor` (w1 `shiftR` 26#)
writeSTRef ref $ XorshiftPlus1 w1 y
return $ W# (w1 `plus` y)
getWord :: XorshiftPlus -> IO Word
getWord = stToIO . getWordST
getInt :: XorshiftPlus -> IO Int
getInt x = do
w <- getWord x
return $ fromIntegral w
getDouble :: XorshiftPlus -> IO Double
getDouble x = do
let maxWord = fromIntegral (maxBound :: Word)
w <- getWord x
return $ (fromIntegral w) / maxWord