packages feed

splitmix 0.0.1 → 0.0.2

raw patch · 4 files changed

+121/−49 lines, 4 filesdep ~basedep ~base-compat-batteriesdep ~bytestring

Dependency ranges changed: base, base-compat-batteries, bytestring, containers, deepseq, process, random, time, vector

Files

Changelog.md view
@@ -1,3 +1,8 @@+# 0.0.2++- Support back to GHC-7.0+- Add `Read SMGen` instance+ # 0.0.1  - Add `NFData SMGen` instance
splitmix.cabal view
@@ -1,8 +1,7 @@-cabal-version:  >= 1.10-name:           splitmix-version:        0.0.1--synopsis:       Fast Splittable PRNG+cabal-version:      >=1.10+name:               splitmix+version:            0.0.2+synopsis:           Fast Splittable PRNG description:   Pure Haskell implementation of SplitMix described in   .@@ -27,19 +26,14 @@   (the mixing functions are easily inverted, and two successive outputs   suffice to reconstruct the internal state). -license:        BSD3-license-file:   LICENSE-maintainer:     Oleg Grenrus <oleg.grenrus@iki.fi>-bug-reports:    https://github.com/phadej/splitmix#issues-category:       System-build-type:     Simple+license:            BSD3+license-file:       LICENSE+maintainer:         Oleg Grenrus <oleg.grenrus@iki.fi>+bug-reports:        https://github.com/phadej/splitmix#issues+category:           System+build-type:         Simple tested-with:-  GHC==7.6.3,-  GHC==7.8.4,-  GHC==7.10.3,-  GHC==8.0.2,-  GHC==8.2.2,-  GHC==8.4.2+  GHC ==8.6.4 || ==8.4.4 || ==8.2.2 || ==8.0.2 || ==7.10.3 || ==7.8.4 || ==7.6.3 || ==7.4.2 || ==7.2.2 || ==7.0.4  extra-source-files:   README.md@@ -49,18 +43,18 @@   default-language: Haskell2010   ghc-options:      -Wall   hs-source-dirs:   src-  exposed-modules:-    System.Random.SplitMix-  build-depends:-    base    >=4.5     && <4.12,-    deepseq >=1.3.0.1 && <1.5,-    time    >=1.4.0.1 && <1.9,-    random  >=1.1     && <1.2+  exposed-modules:  System.Random.SplitMix    -- dump-core   -- build-depends: dump-core   -- ghc-options: -fplugin=DumpCore -fplugin-opt DumpCore:core-html +  build-depends:+      base     >=4.3     && <4.13+    , deepseq  >=1.3.0.0 && <1.5+    , random   >=1.0     && <1.2+    , time     >=1.2.0.3 && <1.9+ source-repository head   type:     git   location: https://github.com/phadej/splitmix.git@@ -72,12 +66,12 @@   hs-source-dirs:   bench   main-is:          Bench.hs   build-depends:-    base,-    splitmix,-    random,-    containers >=0.5     && <0.6,-    tf-random  >=0.5     && <0.6,-    criterion  >=1.1.0.0 && <1.5+      base+    , containers  >=0.4.2.1 && <0.7+    , criterion   >=1.1.0.0 && <1.6+    , random+    , splitmix+    , tf-random   >=0.5     && <0.6  test-suite montecarlo-pi   type:             exitcode-stdio-1.0@@ -86,8 +80,8 @@   hs-source-dirs:   tests   main-is:          SplitMixPi.hs   build-depends:-    base,-    splitmix+      base+    , splitmix  test-suite splitmix-dieharder   type:             exitcode-stdio-1.0@@ -96,13 +90,13 @@   hs-source-dirs:   tests   main-is:          Dieharder.hs   build-depends:-    base,-    splitmix,-    random,-    deepseq,-    async                 >=2.2.1    && <2.3,-    vector                >=0.12.0.1 && <0.13,-    base-compat-batteries >=0.10.1   && <0.11,-    bytestring            >=0.10.4.0 && <0.11,-    process               >=1.1.0.2  && <1.7,-    tf-random             >=0.5      && <0.6+      async                  >=2.2.1    && <2.3+    , base+    , base-compat-batteries  >=0.10.5   && <0.11+    , bytestring             >=0.9.1.8  && <0.11+    , deepseq+    , process                >=1.0.1.5  && <1.7+    , random+    , splitmix+    , tf-random              >=0.5      && <0.6+    , vector                 >=0.11.0.0 && <0.13
src/System/Random/SplitMix.hs view
@@ -23,7 +23,16 @@ --  because generated sequences of pseudorandom values are too predictable --  (the mixing functions are easily inverted, and two successive outputs --  suffice to reconstruct the internal state).+--+--  Note: This module supports all GHCs since GHC-7.0.4,+--  but GHC-7.0 and GHC-7.2 have slow implementation, as there+--  are no native 'popCount'.+--+{-# LANGUAGE CPP #-}+{-# LANGUAGE BangPatterns #-}+#if __GLASGOW_HASKELL__ >= 702 {-# LANGUAGE Trustworthy #-}+#endif module System.Random.SplitMix (     SMGen,     nextWord64,@@ -40,7 +49,7 @@     ) where  import Control.DeepSeq       (NFData (..))-import Data.Bits             (popCount, shiftL, shiftR, xor, (.|.))+import Data.Bits             (shiftL, shiftR, xor, (.|.)) import Data.IORef            (IORef, atomicModifyIORef, newIORef) import Data.Time.Clock.POSIX (getPOSIXTime) import Data.Word             (Word32, Word64)@@ -49,25 +58,62 @@  import qualified System.Random as R +#if MIN_VERSION_base(4,5,0)+import Data.Bits             (popCount)+#else+import Data.Bits             ((.&.))+popCount :: Word64 -> Int+popCount = go 0+ where+   go !c 0 = c+   go c w = go (c+1) (w .&. (w - 1)) -- clear the least significant+#endif++-- $setup+-- >>> import Text.Read (readMaybe)+-- >>> import Data.List (unfoldr)+-- >>> import Text.Printf (printf)+ ------------------------------------------------------------------------------- -- Generator -------------------------------------------------------------------------------  -- | SplitMix generator state.-data SMGen = SMGen-    { _seed  :: !Word64-    , _gamma :: !Word64  -- ^ always odd-    }+data SMGen = SMGen !Word64 !Word64 -- seed and gamma; gamma is odd   deriving Show  instance NFData SMGen where     rnf (SMGen _ _) = () +-- |+--+-- >>> readMaybe "SMGen 1 1" :: Maybe SMGen+-- Just (SMGen 1 1)+--+-- >>> readMaybe "SMGen 1 2" :: Maybe SMGen+-- Nothing+--+-- >>> readMaybe (show (mkSMGen 42)) :: Maybe SMGen+-- Just (SMGen 9297814886316923340 13679457532755275413)+--+instance Read SMGen where+    readsPrec d r =  readParen (d > 10) (\r0 ->+      [ (SMGen seed gamma, r3)+      | ("SMGen", r1) <- lex r0+      , (seed, r2) <- readsPrec 11 r1+      , (gamma, r3) <- readsPrec 11 r2+      , odd gamma+      ]) r+ ------------------------------------------------------------------------------- -- Operations -------------------------------------------------------------------------------  -- | Generate a 'Word64'.+--+-- >>> take 3 $ map (printf "%x") $ unfoldr (Just . nextWord64) (mkSMGen 1337) :: [String]+-- ["b5c19e300e8b07b3","d600e0e216c0ac76","c54efc3b3cc5af29"]+-- nextWord64 :: SMGen -> (Word64, SMGen) nextWord64 (SMGen seed gamma) = (mix64 seed', SMGen seed' gamma)   where@@ -79,6 +125,10 @@     (w64, g') -> (fromIntegral w64, g')  -- | Generate a 'Double' in @[0, 1)@ range.+--+-- >>> take 8 $ map (printf "%0.3f") $ unfoldr (Just . nextDouble) (mkSMGen 1337) :: [String]+-- ["0.710","0.836","0.771","0.409","0.297","0.527","0.589","0.067"]+-- nextDouble :: SMGen -> (Double, SMGen) nextDouble g = case nextWord64 g of     (w64, g') -> (fromIntegral (w64 `shiftR` 11) * doubleUlp, g')@@ -144,6 +194,10 @@ -------------------------------------------------------------------------------  -- | Create 'SMGen' using seed and gamma.+--+-- >>> seedSMGen 2 2+-- SMGen 2 3+-- seedSMGen     :: Word64 -- ^ seed     -> Word64 -- ^ gamma@@ -159,6 +213,10 @@ unseedSMGen (SMGen seed gamma) = (seed, gamma)  -- | Preferred way to deterministically construct 'SMGen'.+--+-- >>> mkSMGen 42+-- SMGen 9297814886316923340 13679457532755275413+-- mkSMGen :: Word64 -> SMGen mkSMGen s = SMGen (mix64 s) (mixGamma (s + goldenGamma)) 
tests/Dieharder.hs view
@@ -9,6 +9,7 @@ import Control.Concurrent.QSem import Control.DeepSeq         (force) import Data.Bits               (shiftL, (.|.))+import Data.Char               (isSpace) import Data.List               (isInfixOf, unfoldr) import Data.Maybe              (fromMaybe) import Data.Word               (Word64)@@ -17,8 +18,7 @@ import GHC.IO.Exception        (IOErrorType (..), IOException (..)) import System.Environment      (getArgs) import System.IO               (Handle, hGetContents)-import Text.Read               (readMaybe)-import Text.Printf (printf)+import Text.Printf             (printf)  import qualified Control.Concurrent.Async     as A import qualified Control.Exception            as E@@ -166,6 +166,21 @@         else return gen' {-# INLINE generate #-} +-------------------------------------------------------------------------------+-- readMaybe+-------------------------------------------------------------------------------++readEither :: Read a => String -> Either String a+readEither s =+  case [ x | (x,rest) <- reads s, all isSpace rest ] of+    [x] -> Right x+    []  -> Left "Prelude.read: no parse"+    _   -> Left "Prelude.read: ambiguous parse"++readMaybe :: Read a => String -> Maybe a+readMaybe s = case readEither s of+                Left _  -> Nothing+                Right a -> Just a ------------------------------------------------------------------------------- -- Do it yourself command line parsing -------------------------------------------------------------------------------