{-# LANGUAGE
CPP,
MultiParamTypeClasses, FlexibleInstances, UndecidableInstances, GADTs,
BangPatterns, RankNTypes,
ScopedTypeVariables
#-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Data.Random.Source.RandomGen
( getRandomPrimFromRandomGenRef
, getRandomPrimFromRandomGenState
) where
import Data.Random.Internal.Source
import System.Random
import Control.Monad.State
import Control.Monad.RWS
import qualified Control.Monad.State.Strict as S
import qualified Control.Monad.RWS.Strict as S
import Data.StateRef
import Data.Word
instance (Monad m1, RandomGen g, ModifyRef (Ref m2 g) m1 g) => RandomSource m1 (Ref m2 g) where
getRandomPrimFrom = getRandomPrimFromRandomGenRef
instance (Monad m, RandomGen g, ModifyRef (IORef g) m g) => RandomSource m (IORef g) where
{-# SPECIALIZE instance RandomSource IO (IORef StdGen) #-}
getRandomPrimFrom = getRandomPrimFromRandomGenRef
getRandomPrimFromRandomGenRef :: (Monad m, ModifyRef sr m g, RandomGen g) =>
sr -> Prim a -> m a
getRandomPrimFromRandomGenRef ref
= atomicModifyReference' ref
. runState
. getRandomPrimFromRandomGenState
atomicModifyReference' :: ModifyRef sr m a => sr -> (a -> (b, a)) -> m b
atomicModifyReference' ref getR =
atomicModifyReference ref (swap' . getR)
where swap' (!a,!b) = (b,a)
getRandomPrimFromRandomGenState :: forall g m a. (RandomGen g, MonadState g m) => Prim a -> m a
getRandomPrimFromRandomGenState = genPrim
where
{-# INLINE genPrim #-}
genPrim :: forall t. Prim t -> m t
genPrim PrimWord8 = getThing (randomR (0, 0xff)) (fromIntegral :: Int -> Word8)
genPrim PrimWord16 = getThing (randomR (0, 0xffff)) (fromIntegral :: Int -> Word16)
genPrim PrimWord32 = getThing (randomR (0, 0xffffffff)) (fromInteger)
genPrim PrimWord64 = getThing (randomR (0, 0xffffffffffffffff)) (fromInteger)
genPrim PrimDouble = getThing (randomR (0, 0x000fffffffffffff)) (flip encodeFloat (-52))
genPrim (PrimNByteInteger n) = getThing (randomR (0, iterate (*256) 1 !! n)) id
{-# INLINE getThing #-}
getThing :: forall b t. (g -> (b, g)) -> (b -> t) -> m t
getThing thing f = do
!oldGen <- get
case thing oldGen of
(!i,!newGen) -> do
put newGen
return (f $! i)
#ifndef MTL2
instance RandomGen g => MonadRandom (State g) where
getRandomPrim = getRandomPrimFromRandomGenState
instance RandomGen g => MonadRandom (S.State g) where
getRandomPrim = getRandomPrimFromRandomGenState
instance (RandomGen g, Monoid w) => MonadRandom (RWS r w g) where
getRandomPrim = getRandomPrimFromRandomGenState
instance (RandomGen g, Monoid w) => MonadRandom (S.RWS r w g) where
getRandomPrim = getRandomPrimFromRandomGenState
#endif
instance (RandomGen g, Monad m) => MonadRandom (StateT g m) where
getRandomPrim = getRandomPrimFromRandomGenState
instance (RandomGen g, Monad m) => MonadRandom (S.StateT g m) where
getRandomPrim = getRandomPrimFromRandomGenState
instance (RandomGen g, Monad m, Monoid w) => MonadRandom (RWST r w g m) where
getRandomPrim = getRandomPrimFromRandomGenState
instance (RandomGen g, Monad m, Monoid w) => MonadRandom (S.RWST r w g m) where
getRandomPrim = getRandomPrimFromRandomGenState