{-# LANGUAGE CPP #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE ScopedTypeVariables #-}
module System.Random.MWC.SeedSource (
acquireSeedSystem
, acquireSeedTime
, randomSourceName
) where
import Control.Monad (liftM)
import Data.Word (Word32,Word64)
import Data.Bits (shiftR)
import Data.Ratio ((%), numerator)
import Data.Time.Clock.POSIX (getPOSIXTime)
import Foreign.Storable
import Foreign.Marshal.Alloc (allocaBytes)
import Foreign.Marshal.Array (peekArray)
#if defined(mingw32_HOST_OS)
import Foreign.Ptr
import Foreign.C.Types
#endif
import System.CPUTime (cpuTimePrecision, getCPUTime)
import System.IO (IOMode(..), hGetBuf, withBinaryFile)
acquireSeedTime :: IO [Word32]
acquireSeedTime :: IO [Word32]
acquireSeedTime = do
Integer
c <- (forall a. Ratio a -> a
numerator forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Integral a => a -> a -> Ratio a
%Integer
cpuTimePrecision)) forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
`liftM` IO Integer
getCPUTime
Ratio Integer
t <- forall a. Real a => a -> Ratio Integer
toRational forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
`liftM` IO POSIXTime
getPOSIXTime
let n :: Word64
n = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Ratio a -> a
numerator Ratio Integer
t) :: Word64
forall (m :: * -> *) a. Monad m => a -> m a
return [forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
c, forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
n, forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
n forall a. Bits a => a -> Int -> a
`shiftR` Int
32)]
acquireSeedSystem :: forall a. Storable a => Int -> IO [a]
acquireSeedSystem :: forall a. Storable a => Int -> IO [a]
acquireSeedSystem Int
nElts = do
let eltSize :: Int
eltSize = forall a. Storable a => a -> Int
sizeOf (forall a. HasCallStack => a
undefined :: a)
nbytes :: Int
nbytes = Int
nElts forall a. Num a => a -> a -> a
* Int
eltSize
#if !defined(mingw32_HOST_OS)
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes Int
nbytes forall a b. (a -> b) -> a -> b
$ \Ptr a
buf -> do
Int
nread <- forall r. FilePath -> IOMode -> (Handle -> IO r) -> IO r
withBinaryFile FilePath
"/dev/urandom" IOMode
ReadMode forall a b. (a -> b) -> a -> b
$ \Handle
h -> forall a. Handle -> Ptr a -> Int -> IO Int
hGetBuf Handle
h Ptr a
buf Int
nbytes
forall a. Storable a => Int -> Ptr a -> IO [a]
peekArray (Int
nread forall a. Integral a => a -> a -> a
`div` Int
eltSize) Ptr a
buf
#else
allocaBytes nbytes $ \buf -> do
ok <- c_RtlGenRandom buf (fromIntegral nbytes)
if ok then return () else fail "Couldn't use RtlGenRandom"
peekArray nElts buf
#if defined(i386_HOST_ARCH)
# define WINDOWS_CCONV stdcall
#elif defined(x86_64_HOST_ARCH)
# define WINDOWS_CCONV ccall
#else
# error Unknown mingw32 architecture!
#endif
foreign import WINDOWS_CCONV unsafe "SystemFunction036"
c_RtlGenRandom :: Ptr a -> CULong -> IO Bool
#endif
randomSourceName :: String
#if !defined(mingw32_HOST_OS)
randomSourceName :: FilePath
randomSourceName = FilePath
"/dev/urandom"
#else
randomSourceName = "RtlGenRandom"
#endif