packages feed

mersenne-random-pure64 0.1.1 → 0.2

raw patch · 8 files changed

+414/−202 lines, 8 filesdep ~base

Dependency ranges changed: base

Files

+ System/Random/Mersenne/Pure64.hs view
@@ -0,0 +1,118 @@+{-# LANGUAGE CPP, ForeignFunctionInterface #-}+--------------------------------------------------------------------+-- |+-- Module     : System.Random.Mersenne.Pure64+-- Copyright  : Copyright (c) 2008, Don Stewart <dons@galois.com>+-- License    : BSD3+-- Maintainer : Don Stewart <dons@galois.com>+-- Stability  : experimental+-- Portability: CPP, FFI+-- Tested with: GHC 6.8.2+--+-- A purely functional binding 64 bit binding to the classic mersenne+-- twister random number generator. This is more flexible than the +-- impure 'mersenne-random' library, at the cost of being much slower.+-- This generator is however, many times faster than System.Random,+-- and yields high quality randoms with a long period.+--+-- This generator may be used with System.Random, however, that is+-- likely to be slower than using it directly.+--+module System.Random.Mersenne.Pure64 (++    -- * The random number generator+    PureMT          -- abstract: RandomGen++    -- * Introduction+    , pureMT        -- :: Word64 -> PureMT+    , newPureMT     -- :: IO PureMT++    -- $instance++    -- * Low level access to the generator++    -- $notes+    , randomInt     -- :: PureMT -> (Int   ,PureMT)+    , randomWord    -- :: PureMT -> (Word  ,PureMT)+    , randomInt64   -- :: PureMT -> (Int64 ,PureMT)+    , randomWord64  -- :: PureMT -> (Word64,PureMT)+    , randomDouble  -- :: PureMT -> (Double,PureMT)++    ) where++------------------------------------------------------------------------++import System.Random.Mersenne.Pure64.MTBlock+import System.Random+import Data.Word+import Data.Int+import System.Time+import System.CPUTime++-- | Create a PureMT generator from a 'Word64' seed.+pureMT :: Word64 -> PureMT+pureMT = mkPureMT . seedBlock . fromIntegral++-- | Create a new PureMT generator, using the clocktime as the base for the seed.+newPureMT :: IO PureMT+newPureMT = do+    ct             <- getCPUTime+    (TOD sec psec) <- getClockTime+    return $ pureMT (fromIntegral $ sec * 1013904242 + psec + ct)++------------------------------------------------------------------------+-- System.Random interface.++-- $instance+--+-- Being purely functional, the PureMT generator is an instance of+-- RandomGen. However, it doesn't support 'split' yet.++instance RandomGen PureMT where+   next  = randomInt+   split = error "System.Random.Mersenne.Pure: unable to split the mersenne twister"++------------------------------------------------------------------------+-- Direct access to Int, Word and Double types++-- | Yield a new 'Int' value from the generator, returning a new+-- generator and that 'Int'. The full 64 bits will be used on a 64 bit machine.+randomInt :: PureMT -> (Int,PureMT)+randomInt g = (fromIntegral i, g')+        where (i,g') = randomWord64 g++-- | Yield a new 'Word' value from the generator, returning a new+-- generator and that 'Word'.+randomWord :: PureMT -> (Word,PureMT)+randomWord g = (fromIntegral i, g')+        where (i,g') = randomWord64 g++-- | Yield a new 'Int64' value from the generator, returning a new+-- generator and that 'Int64'.+randomInt64 :: PureMT -> (Int64,PureMT)+randomInt64 g = (fromIntegral i, g')+        where (i,g') = randomWord64 g++-- | Efficiently yield a new 53-bit precise 'Double' value, and a new generator.+randomDouble :: PureMT -> (Double,PureMT)+randomDouble g = (fromIntegral (i `div` 2048) / 9007199254740992, g')+        where (i,g') = randomWord64 g++-- | Yield a new 'Word64' value from the generator, returning a new+-- generator and that 'Word64'.+randomWord64 :: PureMT -> (Word64,PureMT)+randomWord64 (PureMT block i nxt) = (mixWord64 (block `lookupBlock` i), mt)+  where+    mt | i < blockLen-1 = PureMT block (i+1) nxt+       | otherwise      = mkPureMT nxt++-- | 'PureMT', a pure mersenne twister pseudo-random number generator+--+data PureMT  = PureMT !MTBlock !Int MTBlock++instance Show PureMT where+    show _ = show "<PureMT>"++-- create a new PureMT from an MTBlock+mkPureMT :: MTBlock -> PureMT+mkPureMT block = PureMT block 0 (nextBlock block)
− System/Random/Mersenne/Pure64.hsc
@@ -1,198 +0,0 @@-{-# LANGUAGE CPP, ForeignFunctionInterface #-}------------------------------------------------------------------------ |--- Module     : System.Random.Mersenne.Pure64--- Copyright  : Copyright (c) 2008, Don Stewart <dons@galois.com>--- License    : BSD3--- Maintainer : Don Stewart <dons@galois.com>--- Stability  : experimental--- Portability: CPP, FFI--- Tested with: GHC 6.8.2------ A purely functional binding 64 bit binding to the classic mersenne--- twister random number generator. This is more flexible than the --- impure 'mersenne-random' library, at the cost of being much slower.--- This generator is however, many times faster than System.Random,--- and yields high quality randoms with a long period.------ This generator may be used with System.Random, however, that is--- likely to be slower than using it directly.----module System.Random.Mersenne.Pure64 (--    -- * The random number generator-    PureMT          -- abstract: RandomGen--    -- * Introduction-    , pureMT        -- :: Word -> PureMT-    , newPureMT     -- :: IO PureMT--    -- $instance--    -- * Low level access to the generator--    -- $notes-    , randomInt     -- :: PureMT -> (Int   ,PureMT)-    , randomWord    -- :: PureMT -> (Word  ,PureMT)-    , randomInt64   -- :: PureMT -> (Int64 ,PureMT)-    , randomWord64  -- :: PureMT -> (Word64,PureMT)-    , randomDouble  -- :: PureMT -> (Double,PureMT)--    ) where----------------------------------------------------------------------------#include "mt19937-64.h"----------------------------------------------------------------------------import System.Random.Mersenne.Pure64.Base--#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 605-import GHC.ForeignPtr           (mallocPlainForeignPtrBytes)-#else-import Foreign.ForeignPtr       (mallocForeignPtrBytes)-#endif--import Foreign.C.Types-import Foreign--import System.CPUTime	( getCPUTime )-import System.Time-import System.IO.Unsafe-import Control.Monad--import System.Random--import Data.Word-import Data.Int------------------------------------------------------------------------------ | Create a PureMT generator from a 'Word' seed.-pureMT :: Word -> PureMT-pureMT = init_genrand64 . fromIntegral---- | Create a new PureMT generator, using the clocktime as the base for the seed.-newPureMT :: IO PureMT-newPureMT = do-    ct             <- getCPUTime-    (TOD sec psec) <- getClockTime-    return $ pureMT (fromIntegral $ sec * 1013904242 + psec + ct)----------------------------------------------------------------------------- System.Random interface.---- $instance --- --- Being purely functional, the PureMT generator is an instance of--- RandomGen. However, it doesn't support 'split' yet.--instance RandomGen PureMT where-   next  = randomInt-   split = error "System.Random.Mersenne.Pure: unable to split the mersenne twister"----------------------------------------------------------------------------- Direct access to Int, Word and Double types---- | Yield a new 'Int' value from the generator, returning a new--- generator and that 'Int'. The full 64 bits will be used on a 64 bit machine.-randomInt :: PureMT -> (Int,PureMT)-randomInt g = (fromIntegral i, g')-        where (i,g') = genrand64_int64 g---- | Yield a new 'Word' value from the generator, returning a new--- generator and that 'Word'. -randomWord :: PureMT -> (Word,PureMT)-randomWord g = (fromIntegral i, g')-        where (i,g') = genrand64_int64 g---- | Yield a new 'Int64' value from the generator, returning a new--- generator and that 'Int64'. -randomInt64 :: PureMT -> (Int64,PureMT)-randomInt64 g = (fromIntegral i, g')-        where (i,g') = genrand64_int64 g---- | Yield a new 'Word64' value from the generator, returning a new--- generator and that 'Word64'. -randomWord64 :: PureMT -> (Word64,PureMT)-randomWord64 g = (fromIntegral i, g')-        where (i,g') = genrand64_int64 g---- | Efficiently yield a new 53-bit precise 'Double' value, and a new generator.-randomDouble :: PureMT -> (Double,PureMT)-randomDouble g = (realToFrac i, g')-        where (i,g') = genrand64_real2 g----------------------------------------------------------------------------- We can have only one mersenne supply in a program.---- You have to commit at initialisation time to call either--- rand_gen32 or rand_gen64, and correspondingly, real2 or res53--- for doubles.------- | 'PureMT', a pure mersenne twister pseudo-random number generator----newtype PureMT  = PureMT (ForeignPtr MTState)--instance Show PureMT where-    show _ = show "<PureMT>"--sizeof_MTState :: Int-sizeof_MTState = (#const (sizeof (struct mt_state_t))) -- 2504 bytes----------------------------------------------------------------------------- Low level interface--init_genrand64 :: UInt64 -> PureMT-init_genrand64 seed = unsafePerformIO $ do-    fp <- mallocFastBytes sizeof_MTState-    withForeignPtr fp $ \p -> c_init_genrand64 p seed -- fill it-    return $ PureMT fp--genrand64_int64 :: PureMT -> (UInt64, PureMT)-genrand64_int64 o   = unsafePerformIO $ do-    PureMT n <- copyPureMT o-    v        <- withForeignPtr n $ c_genrand64_int64-    n `seq` v `seq`-        return (v,PureMT n)-{-# INLINE genrand64_int64 #-}--genrand64_real2 :: PureMT -> (CDouble, PureMT)-genrand64_real2 o   = unsafePerformIO $ do-    PureMT n <- copyPureMT o-    v        <- withForeignPtr n $ c_genrand64_real2-    n `seq` v `seq`-        return (v,PureMT n)-{-# INLINE genrand64_real2 #-}---- ------------------------------------------------------------------------ Memory management------- | Wrapper of mallocForeignPtrBytes with faster implementation--- Allocate pinned heap memory for the state.----mallocFastBytes :: Int -> IO (ForeignPtr a)-mallocFastBytes s = do-#if __GLASGOW_HASKELL__ >= 605 && !defined(SLOW_FOREIGN_PTR)-    mallocPlainForeignPtrBytes s-#else-    mallocForeignPtrBytes s-#endif-{-# INLINE mallocFastBytes #-}------- Duplicate a random state, prior to permuting it.----copyPureMT :: PureMT -> IO PureMT-copyPureMT (PureMT oldfp) = do-    newfp <- mallocFastBytes sizeof_MTState-    withForeignPtr newfp $ \p ->-        withForeignPtr oldfp $ \q ->-            c_memcpy (castPtr p) (castPtr q) (fromIntegral sizeof_MTState)-    return $! PureMT newfp-{-# INLINE copyPureMT #-}--
System/Random/Mersenne/Pure64/Base.hsc view
@@ -1,7 +1,7 @@ {-# LANGUAGE EmptyDataDecls, CPP, ForeignFunctionInterface #-} -------------------------------------------------------------------- -- |--- Module     : System.Random.Mersenne.Pure64+-- Module     : System.Random.Mersenne.Pure64.Base -- Copyright  : Copyright (c) 2008, Don Stewart <dons@galois.com> -- License    : BSD3 -- Maintainer : Don Stewart <dons@galois.com>@@ -17,6 +17,7 @@ -- module System.Random.Mersenne.Pure64.Base where +#include "mt19937-64-block.h" #include "mt19937-64.h" #include "mt19937-64-unsafe.h" @@ -38,6 +39,28 @@  foreign import ccall unsafe "genrand64_real2"     c_genrand64_real2 :: Ptr MTState -> IO CDouble++sizeof_MTState :: Int+sizeof_MTState = (#const (sizeof (struct mt_state_t))) -- 2504 bytes++------------------------------------------------------------------------+-- block based version:+foreign import ccall unsafe "mix_bits"+    c_mix_word64 :: Word64 -> Word64++foreign import ccall unsafe "seed_genrand64_block"+    c_seed_genrand64_block :: Ptr a -> Word64 -> IO ()++foreign import ccall unsafe "next_genrand64_block"+    c_next_genrand64_block :: Ptr a -> Ptr a -> IO ()++-- | length of an MT block+blockLen :: Int+blockLen = (# const NN )++-- | size of an MT block, in bytes+blockSize :: Int+blockSize = (# const sizeof(mt_block_struct) )  ------------------------------------------------------------------------ -- model: (for testing purposes)
+ System/Random/Mersenne/Pure64/MTBlock.hs view
@@ -0,0 +1,86 @@+{-# LANGUAGE MagicHash, UnboxedTuples #-}+--------------------------------------------------------------------+-- |+-- Module     : System.Random.Mersenne.Pure64+-- Copyright  : Copyright (c) 2008, Bertram Felgenhauer <dons@galois.com>+-- License    : BSD3+-- Maintainer : Don Stewart <dons@galois.com>+-- Stability  : experimental+-- Portability: +-- Tested with: GHC 6.8.2+--+module System.Random.Mersenne.Pure64.MTBlock (+    -- * Block type+    MTBlock,++    -- * Block functions+    seedBlock,+    nextBlock,+    lookupBlock,++    -- * Misc functions+    blockLen,+    mixWord64,+) where++import GHC.Exts+import GHC.IOBase+import GHC.Word+import System.Random.Mersenne.Pure64.Base++data MTBlock = MTBlock ByteArray#++allocateBlock :: IO MTBlock+allocateBlock =+    IO $ \s0 -> case newPinnedByteArray# blockSize# s0 of+        (# s1, b0 #) -> case unsafeFreezeByteArray# b0 s1 of+            (# s2, b1 #) -> (# s2, MTBlock b1 #)+  where+    I# blockSize# = blockSize++blockAsPtr :: MTBlock -> Ptr a+blockAsPtr (MTBlock b) = Ptr (byteArrayContents# b)++-- | create a new MT block, seeded with the given Word64 value+seedBlock :: Word64 -> MTBlock+seedBlock seed = unsafePerformIO $ do+    b <- allocateBlock+    c_seed_genrand64_block (blockAsPtr b) seed+    c_next_genrand64_block (blockAsPtr b) (blockAsPtr b)+    touch b+    return b++-- | step: create a new MTBlock buffer from the previous one+nextBlock :: MTBlock -> MTBlock+nextBlock b = unsafePerformIO $ do+    new <- allocateBlock+    c_next_genrand64_block (blockAsPtr b) (blockAsPtr new)+    touch b+    touch new+    return new++-- stolen from GHC.ForeignPtr - make sure the argument is still alive.+touch :: a -> IO ()+touch r = IO $ \s0 -> case touch# r s0 of s1 -> (# s1, () #)++-- | look up an element of an MT block+lookupBlock :: MTBlock -> Int -> Word64+lookupBlock (MTBlock b) (I# i) = W64# (indexWord64Array# b i)++-- | MT's word mix function.+--+-- (MT applies this function to each Word64 from the buffer before returning it)+mixWord64 :: Word64 -> Word64+mixWord64 = c_mix_word64++-- Alternative implementation - it's probably faster on 64 bit machines, but+-- on Athlon XP it loses.+{-+mixWord64 (W64# x0) = let+    W64# x1 = W64# x0 `xor` (W64# (x0 `uncheckedShiftRL64#` 28#) .&. 0x5555555555555555)+    W64# x2 = W64# x1 `xor` (W64# (x1 `uncheckedShiftL64#` 17#) .&. 0x71D67FFFEDA60000)+    W64# x3 = W64# x2 `xor` (W64# (x2 `uncheckedShiftL64#` 37#) .&. 0xFFF7EEE000000000)+    W64# x4 = W64# x3 `xor` (W64# (x3 `uncheckedShiftRL64#` 43#))+  in+    W64# x4+-}
TODO view
@@ -1,4 +1,12 @@ -fvia-C seems to break things!+   The problem is that the prototypes of the imported functions don't get+   propagated properly, leading to warnings like this:++   /tmp/ghc7602_0/ghc7602_0.hc:718:0:+        warning: implicit declaration of function 'mix_bits'++   This is actually an error on 32 bit machines - the default return type+   int is not large enough to hold the 64 bit result. Check sequences are repeatable check behaviour on 32 bits profile/benchmark
+ cbits/mt19937-64-block.c view
@@ -0,0 +1,99 @@+/* +   A C-program for MT19937-64 (2004/9/29 version).+   Coded by Takuji Nishimura and Makoto Matsumoto.++   This is a 64-bit version of Mersenne Twister pseudorandom number+   generator.++   Copyright (C) 2004, Makoto Matsumoto and Takuji Nishimura,+   All rights reserved.                          ++   Redistribution and use in source and binary forms, with or without+   modification, are permitted provided that the following conditions+   are met:++     1. Redistributions of source code must retain the above copyright+        notice, this list of conditions and the following disclaimer.++     2. Redistributions in binary form must reproduce the above copyright+        notice, this list of conditions and the following disclaimer in the+        documentation and/or other materials provided with the distribution.++     3. The names of its contributors may not be used to endorse or promote +        products derived from this software without specific prior written +        permission.++   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.++   References:+   T. Nishimura, ``Tables of 64-bit Mersenne Twisters''+     ACM Transactions on Modeling and +     Computer Simulation 10. (2000) 348--357.+   M. Matsumoto and T. Nishimura,+     ``Mersenne Twister: a 623-dimensionally equidistributed+       uniform pseudorandom number generator''+     ACM Transactions on Modeling and +     Computer Simulation 8. (Jan. 1998) 3--30.++   Any feedback is very welcome.+   http://www.math.hiroshima-u.ac.jp/~m-mat/MT/emt.html+   email: m-mat @ math.sci.hiroshima-u.ac.jp (remove spaces)++   Modified by Don Stewart to use non-global state.+   Modified by Bertram Felgenhauer to provide block oriented functions only.+*/+++#include <stdio.h>+#include <stdlib.h>+#include "mt19937-64-block.h"++/*+ * When passed an empty state, initialize the states' mt[NN] with a seed+ */+void seed_genrand64_block(mt_block st, unsigned long long seed)+{+    int i;+    st->mt[0] = seed;+    for (i=1; i<NN; i++) +        st->mt[i] =  (6364136223846793005ULL * +                                (st->mt[i-1] ^ (st->mt[i-1] >> 62)) + i);+}++/* generates a new state buffer from the previous one */+void next_genrand64_block(mt_block st, mt_block newst)+{+    int i;+    unsigned long long x;+    static unsigned long long mag01[2]={0ULL, MATRIX_A};++    for (i=0; i<NN-MM; i++) {+        x = (st->mt[i]&UM)|(st->mt[i+1]&LM);+        newst->mt[i] = st->mt[i+MM] ^ (x>>1) ^ mag01[(int)(x&1ULL)];+    }+    for (; i<NN-1; i++) {+        x = (st->mt[i]&UM)|(st->mt[i+1]&LM);+        newst->mt[i] = newst->mt[i+(MM-NN)] ^ (x>>1) ^ mag01[(int)(x&1ULL)];+    }+    x = (st->mt[NN-1]&UM)|(newst->mt[0]&LM);+    newst->mt[NN-1] = newst->mt[MM-1] ^ (x>>1) ^ mag01[(int)(x&1ULL)];+}++unsigned long long mix_bits(unsigned long long x)+{+    x ^= (x >> 29) & 0x5555555555555555ULL;+    x ^= (x << 17) & 0x71D67FFFEDA60000ULL;+    x ^= (x << 37) & 0xFFF7EEE000000000ULL;+    x ^= (x >> 43);+    return x;+}
+ include/mt19937-64-block.h view
@@ -0,0 +1,73 @@+/* +   A C-program for MT19937-64 (2004/9/29 version).+   Coded by Takuji Nishimura and Makoto Matsumoto.++   This is a 64-bit version of Mersenne Twister pseudorandom number+   generator.++   Before using, initialize the state by using init_genrand64(seed)  +   or init_by_array64(init_key, key_length).++   Copyright (C) 2004, Makoto Matsumoto and Takuji Nishimura,+   All rights reserved.                          ++   Redistribution and use in source and binary forms, with or without+   modification, are permitted provided that the following conditions+   are met:++     1. Redistributions of source code must retain the above copyright+        notice, this list of conditions and the following disclaimer.++     2. Redistributions in binary form must reproduce the above copyright+        notice, this list of conditions and the following disclaimer in the+        documentation and/or other materials provided with the distribution.++     3. The names of its contributors may not be used to endorse or promote +        products derived from this software without specific prior written +        permission.++   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.++   References:+   T. Nishimura, ``Tables of 64-bit Mersenne Twisters''+     ACM Transactions on Modeling and +     Computer Simulation 10. (2000) 348--357.+   M. Matsumoto and T. Nishimura,+     ``Mersenne Twister: a 623-dimensionally equidistributed+       uniform pseudorandom number generator''+     ACM Transactions on Modeling and +     Computer Simulation 8. (Jan. 1998) 3--30.++   Any feedback is very welcome.+   http://www.math.hiroshima-u.ac.jp/~m-mat/MT/emt.html+   email: m-mat @ math.sci.hiroshima-u.ac.jp (remove spaces)+*/++#define NN 312+#define MM 156+#define MATRIX_A 0xB5026F5AA96619E9ULL+#define UM 0xFFFFFFFF80000000ULL /* Most significant 33 bits */+#define LM 0x7FFFFFFFULL /* Least significant 31 bits */++/* The array for the state vector */+typedef struct mt_block_t {+    unsigned long long mt[NN]; +} mt_block_struct, *mt_block;++/* initializes mt[NN] with a seed */+void seed_genrand64_block(mt_block st, unsigned long long seed);++/* calculate new block of random data */+void next_genrand64_block(mt_block st, mt_block newst);++unsigned long long mix_bits(unsigned long long x);
mersenne-random-pure64.cabal view
@@ -1,5 +1,5 @@ name:            mersenne-random-pure64-version:         0.1.1+version:         0.2 homepage:        http://code.haskell.org/~dons/code/mt19937-random synopsis:        Generate high quality pseudorandom numbers purely using a Mersenne Twister description:@@ -25,7 +25,7 @@ author:          Don Stewart maintainer:      Don Stewart <dons@galois.com> cabal-version: >= 1.2.0-build-type:      Configure+build-type:      Simple tested-with:     GHC ==6.8.2  flag small_base@@ -35,6 +35,7 @@ library     exposed-modules: System.Random.Mersenne.Pure64                      System.Random.Mersenne.Pure64.Base+                     System.Random.Mersenne.Pure64.MTBlock     extensions:      CPP, ForeignFunctionInterface      if flag(small_base)@@ -46,11 +47,13 @@         -O3 -finline-functions -fomit-frame-pointer         -fno-strict-aliasing --param max-inline-insns-single=1800 -    ghc-options:     -Wall -O2 -fvia-C -fexcess-precision+    ghc-options:     -Wall -O2 -fexcess-precision      c-sources:        cbits/mt19937-64.c                       cbits/mt19937-64-unsafe.c+                      cbits/mt19937-64-block.c     include-dirs:     include     includes:     install-includes: mt19937-64.h                       mt19937-64-unsafe.h+                      mt19937-64-block.h