splitmix-distributions 1.0.0 → 1.1.0
raw patch · 4 files changed
+45/−7 lines, 4 files
Files
- ChangeLog.md +6/−0
- README.md +2/−0
- splitmix-distributions.cabal +3/−6
- src/System/Random/SplitMix/Distributions.hs +34/−1
ChangeLog.md view
@@ -1,3 +1,9 @@+1.1++- add sampleRunT and samplesRunT: both return the final state of the PRNG as a tuple of Word64+- add unit test that asserts that sample runs are deterministic given the same starting PRNG state+- + 1.0 - add MonadReader r (GenT m) instance
README.md view
@@ -1,5 +1,7 @@ # splitmix-distributions +[](https://github.com/ocramz/splitmix-distributions/actions/workflows/ci.yaml)+ Random samplers for some common distributions, as well as a convenient interface for composing them, based on `splitmix`.
splitmix-distributions.cabal view
@@ -1,5 +1,5 @@ name: splitmix-distributions-version: 1.0.0+version: 1.1.0 description: Random samplers for some common distributions, as well as a convenient interface for composing them, based on splitmix. Please see the README on GitHub at <https://github.com/ocramz/splitmix-distributions#readme> homepage: https://github.com/ocramz/splitmix-distributions#readme bug-reports: https://github.com/ocramz/splitmix-distributions/issues@@ -12,7 +12,7 @@ license-file: LICENSE build-type: Simple cabal-version: >= 1.10-tested-with: GHC == 8.6.5, GHC == 8.10.4+tested-with: GHC == 8.6.5, GHC == 8.10.4, GHC == 9.6.6 extra-source-files: README.md ChangeLog.md@@ -35,6 +35,7 @@ , splitmix , transformers default-language: Haskell2010+ ghc-options: -Wall test-suite test type: exitcode-stdio-1.0@@ -44,10 +45,6 @@ ghc-options: -threaded -rtsopts -with-rtsopts=-N build-depends: base >=4.7 && <5- , erf , hspec- , mtl- , splitmix , splitmix-distributions- , transformers default-language: Haskell2010
src/System/Random/SplitMix/Distributions.hs view
@@ -58,10 +58,14 @@ zipf, crp, -- * PRNG+ SMGenState, -- ** Pure Gen, sample, samples, -- ** Monadic GenT, sampleT, samplesT,+ -- *** Return final PRNG state+ sampleRunT,+ samplesRunT, -- ** IO-based sampleIO, samplesIO, -- ** splitmix utilities@@ -70,6 +74,7 @@ import Control.Monad (replicateM) import Control.Monad.IO.Class (MonadIO(..))+import Data.Bifunctor (second) import Data.Foldable (toList) import Data.Functor.Identity (Identity(..)) import Data.List (findIndex)@@ -87,7 +92,7 @@ import Control.Monad.Reader (MonadReader(..)) import Control.Monad.State (MonadState(..), modify) -- splitmix-import System.Random.SplitMix (SMGen, mkSMGen, initSMGen, unseedSMGen, splitSMGen, nextDouble)+import System.Random.SplitMix (SMGen, mkSMGen, seedSMGen', initSMGen, unseedSMGen, splitSMGen, nextDouble) -- transformers import Control.Monad.Trans.Reader (ReaderT(..)) import Control.Monad.Trans.State (StateT(..), runStateT, evalStateT, State, runState, evalState)@@ -115,6 +120,16 @@ -> m a sampleT seed gg = evalStateT (unGen gg) (mkSMGen seed) +-- | Sample in a monadic context, returning the final PRNG state as well+--+-- This makes it possible to have deterministic chains of invocations, for reproducible results+sampleRunT :: (Functor m) =>+ SMGenState -- ^ random seed+ -> GenT m a+ -> m (a, SMGenState) -- ^ (result, final PRNG state)+sampleRunT seed gg = second unseedSMGen <$> runStateT (unGen gg) (seedSMGen' seed)++ -- | Initialize a splitmix random generator from system entropy (current time etc.) and sample from the PRNG. sampleIO :: MonadIO m => GenT m b -> m b sampleIO gg = do@@ -128,6 +143,24 @@ -> GenT m a -> m [a] samplesT n seed gg = sampleT seed (replicateM n gg)++-- | Sample a batch in a monadic context, returning the final PRNG state as well+--+-- Same as @n@ repeated invocations of `sampleRunT`, while threading the PRNG state.+samplesRunT :: Monad m =>+ Int -- ^ size of sample+ -> SMGenState -- ^ random seed+ -> GenT m a+ -> m ([a], SMGenState) -- ^ (result, final PRNG state)+samplesRunT n seed gg = second unseedSMGen <$> runStateT (replicateM n $ unGen gg) (seedSMGen' seed)++-- | Internal state of the splitmix PRNG.+--+-- This representation has the benefit of being serializable (e.g. can be passed back and forth between API calls)+type SMGenState = (Word64, Word64)++-- getSeed :: SMGen -> Word64+-- getSeed = fst . unseedSMGen -- | Initialize a splitmix random generator from system entropy (current time etc.) and sample n times from the PRNG. samplesIO :: MonadIO m => Int -> GenT m a -> m [a]