{-# LANGUAGE BangPatterns #-}
module System.Random.MRG63k3a.Internal
(
norm
, m1
, m2
, mrg63k3a_rec
, jmtxs
) where
import System.Random.MRG.Internal
import Data.Int (Int64)
import Data.Word (Word64)
import Data.List (unfoldr)
norm :: Double
norm = 1.0842021724855052e-19
{-# INLINE norm #-}
m1 :: Int64
m1 = 9223372036854769163
{-# INLINE m1 #-}
m2 :: Int64
m2 = 9223372036854754679
{-# INLINE m2 #-}
a12 :: Int64
a12 = 1754669720
{-# INLINE a12 #-}
q12 :: Int64
q12 = 5256471877
{-# INLINE q12 #-}
r12 :: Int64
r12 = 251304723
{-# INLINE r12 #-}
a13n :: Int64
a13n = 3182104042
{-# INLINE a13n #-}
q13 :: Int64
q13 = 2898513661
{-# INLINE q13 #-}
r13 :: Int64
r13 = 394451401
{-# INLINE r13 #-}
a21 :: Int64
a21 = 31387477935
{-# INLINE a21 #-}
q21 :: Int64
q21 = 293855150
{-# INLINE q21 #-}
r21 :: Int64
r21 = 143639429
{-# INLINE r21 #-}
a23n :: Int64
a23n = 6199136374
{-# INLINE a23n #-}
q23 :: Int64
q23 = 1487847900
{-# INLINE q23 #-}
r23 :: Int64
r23 = 985240079
{-# INLINE r23 #-}
mrg63k3a_rec :: (Int64,Int64,Int64,Int64,Int64,Int64) -> (Int64,Int64)
mrg63k3a_rec (s10,s11,_ ,s20,_ ,s22)
= (t1,t2)
where (h10,j10) = s10 `divMod` q13
p13 = a13n * j10 - h10 * r13
p13' = if p13 < 0 then p13 + m1 else p13
(h11,j11) = s11 `divMod` q12
p12 = a12 * j11 - h11 * r12
p12' = if p12 < 0 then p12 + m1 - p13' else p12 - p13'
!t1 = if p12' < 0 then p12' + m1 else p12'
(h20,j20) = s20 `divMod` q23
p23 = a23n * j20 - h20 * r23
p23' = if p23 < 0 then p23 + m2 else p23
(h22,j22) = s22 `divMod` q21
p21 = a21 * j22 - h22 * r21
p21' = if p21 < 0 then p21 + m2 - p23' else p21 - p23'
!t2 = if p21' < 0 then p21' + m2 else p21'
{-# INLINE mrg63k3a_rec #-}
mtx1 :: JumpMatrix Int64
mtx1 = JM (0, 1, 0) (0, 0, 1) (m1 - a13n, a12, 0)
mtx2 :: JumpMatrix Int64
mtx2 = JM (0, 1, 0) (0, 0, 1) (m2 - a23n, 0, a21)
cntdn :: (a -> a) -> (a, Int) -> Maybe (a, (a, Int))
cntdn _ (_, 0) = Nothing
cntdn f (x, k) = Just (y, (y, k-1))
where y = f x
jmtxs :: [(JumpMatrix Word64, JumpMatrix Word64)]
jmtxs = zip xs ys
where n = 64
m1' = fromIntegral m1 :: Word64
m2' = fromIntegral m2 :: Word64
mtx1' = fromIntegral <$> mtx1
xs = mtx1' : unfoldr (cntdn (matSqrModW64 m1')) (mtx1',n)
mtx2' = fromIntegral <$> mtx2
ys = mtx2' : unfoldr (cntdn (matSqrModW64 m2')) (mtx2',n)