{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveDataTypeable #-}
module System.Random.MRG63k3a
(
Gen
, initialize
, uniform01
, Seed
, fromSeed
, save
, restore
, jump
) where
import Data.Typeable (Typeable)
import Data.Int (Int64)
import Data.Word (Word8,Word16,Word32,Word64)
import Data.Bits ((.&.))
import System.Random
import System.Random.MRG.Internal
import System.Random.MRG63k3a.Internal
data Gen = Gen (Int64,Int64,Int64,Int64,Int64,Int64)
instance RandomGen Gen where
genWord32 = uniformW32
genWord16 = uniformW16
genWord8 = uniformW8
split _ = error "Not yet implemented."
{-# INLINE genWord32 #-}
{-# INLINE genWord16 #-}
{-# INLINE genWord8 #-}
mrg63k3a_genRand :: Gen -> (Int64,Gen)
mrg63k3a_genRand (Gen s@(_ ,s11,s12,_ ,s21,s22))
= (v, Gen (s11,s12,t1,s21,s22,t2))
where (t1,t2) = mrg63k3a_rec s
v = if t1 > t2 then t1 - t2 else t1 - t2 + m1
{-# INLINE mrg63k3a_genRand #-}
initialize :: Int64 -> Gen
initialize seed = Gen (s1,s1,s1,s2,s2,s2)
where s1 = seed `mod` m1
s2 = seed `mod` m2
{-# INLINE initialize #-}
uniform01 :: Gen -> (Double, Gen)
uniform01 gen = (w,gen')
where (v,gen') = mrg63k3a_genRand gen
!w = norm * fromIntegral v
{-# INLINE uniform01 #-}
ub32 :: Int64
ub32 = v
where !r = m1 `mod` 4294967296
!v = m1 - r
{-# INLINE ub32 #-}
uniformW32 :: Gen -> (Word32, Gen)
uniformW32 gen = go gen
where go g = if x >= ub32 then go g' else (fromIntegral (x .&. 4294967295), g')
where (x,g') = mrg63k3a_genRand g
{-# INLINE uniformW32 #-}
ub16 :: Int64
ub16 = v
where !r = m1 `mod` 65536
!v = m1 - r
{-# INLINE ub16 #-}
uniformW16 :: Gen -> (Word16, Gen)
uniformW16 gen = go gen
where go g = if x >= ub16 then go g' else (fromIntegral (x .&. 65535), g')
where (x, g') = mrg63k3a_genRand g
{-# INLINE uniformW16 #-}
ub8 :: Int64
ub8 = v
where !r = m1 `mod` 256
!v = m1 - r
{-# INLINE ub8 #-}
uniformW8 :: Gen -> (Word8, Gen)
uniformW8 gen = go gen
where go g = if x >= ub8 then go g' else (fromIntegral (x .&. 255), g')
where (x, g') = mrg63k3a_genRand g
{-# INLINE uniformW8 #-}
newtype Seed = Seed {
fromSeed :: (Word64,Word64,Word64,Word64,Word64,Word64)
}
deriving (Eq, Show, Typeable)
save :: Gen -> Seed
save (Gen s) = Seed (fromT6 t)
where t = fromIntegral <$> T6 s
{-# INLINE save #-}
restore :: Seed -> Gen
restore (Seed (t1,t2,t3,t4,t5,t6)) = Gen (fromT6 s)
where m1' = fromIntegral m1
m2' = fromIntegral m2
t = T6 (t1 `mod` m1', t2 `mod` m1', t3 `mod` m1',
t4 `mod` m2', t5 `mod` m2', t6 `mod` m2')
s = fromIntegral <$> t
{-# INLINE restore #-}
jump :: Int -> Gen -> Gen
jump e (Gen (s10,s11,s12,s20,s21,s22))
| e > 64 || e < 0 = error "Jump factor must be in the range of [0,64]"
| otherwise = Gen (t10,t11,t12,t20,t21,t22)
where m1' = fromIntegral m1
m2' = fromIntegral m2
v1 = fromIntegral <$> SV (s10, s11, s12)
v2 = fromIntegral <$> SV (s20, s21, s22)
(b1,b2) = jmtxs !! e
w1 = vecTrModW64 m1' b1 v1
w2 = vecTrModW64 m2' b2 v2
SV (!t10,!t11,!t12) = fromIntegral <$> w1
SV (!t20,!t21,!t22) = fromIntegral <$> w2