Skip to content

Commit

Permalink
Merge pull request #98 from lehins/lehins/add-random-seed-instance-al…
Browse files Browse the repository at this point in the history
…ternative

V2: Add an instance for the new SeedGen type class
  • Loading branch information
Shimuuar authored Jan 11, 2025
2 parents 413afd6 + 4f3c865 commit c134e61
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 5 deletions.
27 changes: 26 additions & 1 deletion System/Random/MWC.hs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{-# LANGUAGE BangPatterns, CPP, DeriveDataTypeable, FlexibleContexts,
{-# LANGUAGE BangPatterns, CPP, DataKinds, DeriveDataTypeable, FlexibleContexts,
FlexibleInstances, MultiParamTypeClasses, MagicHash, Rank2Types,
ScopedTypeVariables, TypeFamilies, UnboxedTuples, TypeOperators
#-}
Expand Down Expand Up @@ -177,6 +177,9 @@ import System.IO.Unsafe (unsafePerformIO)
import qualified Control.Exception as E
import System.Random.MWC.SeedSource
import qualified System.Random.Stateful as Random
#if MIN_VERSION_random(1,3,0)
import Data.List.NonEmpty (NonEmpty(..), toList)
#endif

-- | NOTE: Consider use of more principled type classes
-- 'Random.Uniform' and 'Random.UniformRange' instead.
Expand Down Expand Up @@ -486,6 +489,28 @@ instance PrimMonad m => Random.ThawedGen Seed m where
#endif
thawGen = restore

#if MIN_VERSION_random(1,3,0)
instance Random.SeedGen Seed where
type SeedSize Seed = 1032 -- == 4 * 258
fromSeed64 seed64 = toSeed $ I.fromListN 258
[ w32
| !w64 <- toList seed64
, !w32 <- [ fromIntegral (w64 `shiftR` 32)
, fromIntegral w64 ]
]
toSeed64 vSeed =
let w32sToW64 :: Word32 -> Word32 -> Word64
w32sToW64 w32u w32l =
(fromIntegral w32u `shiftL` 32) .|. fromIntegral w32l
v = fromSeed vSeed
evens = I.ifilter (\i _ -> even i) v
odds = I.ifilter (\i _ -> odd i) v
in case I.toList $ I.zipWith w32sToW64 evens odds of
[] ->
error $ "Impossible: Seed had an unexpected length of: " ++ show (I.length v)
x:xs -> x :| xs
#endif

-- | Convert vector to 'Seed'. It acts similarly to 'initialize' and
-- will accept any vector. If you want to pass seed immediately to
-- restore you better call initialize directly since following law holds:
Expand Down
13 changes: 11 additions & 2 deletions bench/Benchmark.hs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
module Main(main) where

import Control.Exception
Expand Down Expand Up @@ -48,8 +49,9 @@ main = do
opts <- parseOptions ingredients (bench "Fake" (nf id ()))
let iter = lookupOption opts
-- Set up RNG
mwc <- create
mtg <- M.newMTGen . Just =<< uniform mwc
mwc <- create
seed <- save mwc

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.12.1 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.12.1 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.2.8 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.2.8 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.10.1 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.10.1 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / macOS-latest / ghc 9.2.8 []

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 8.2.2 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 8.2.2 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 8.8.4 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 8.8.4 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 8.4.4 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 8.4.4 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 8.6.5 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 8.6.5 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.0.2 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.0.2 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 8.10.7 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 8.10.7 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.4.8 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.4.8 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / macOS-13 / ghc 9.0.2 []

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.6.6 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.6.6 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / macOS-latest / ghc 9.4.8 []

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / macOS-13 / ghc 8.6.5 []

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / macOS-latest / ghc 9.6.6 []

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.8.4 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.8.4 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / macOS-latest / ghc 9.8.4 []

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / macOS-13 / ghc 8.4.4 []

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / macOS-latest / ghc 9.10.1 []

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / macOS-13 / ghc 8.8.4 []

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / windows-latest / ghc 9.0.2 []

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 8.0.2 [1.2]

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / macOS-13 / ghc 8.10.7 []

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / macOS-latest / ghc 9.12.1 []

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / windows-latest / ghc 9.6.6 []

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / windows-latest / ghc 8.10.7 []

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / windows-latest / ghc 9.4.8 []

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / windows-latest / ghc 9.2.8 []

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / windows-latest / ghc 9.10.1 []

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / windows-latest / ghc 9.8.4 []

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / windows-latest / ghc 8.6.5 []

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / windows-latest / ghc 8.4.4 []

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / windows-latest / ghc 8.8.4 []

Defined but not used: ‘seed’

Check warning on line 53 in bench/Benchmark.hs

View workflow job for this annotation

GitHub Actions / windows-latest / ghc 9.12.1 []

Defined but not used: ‘seed’
mtg <- M.newMTGen . Just =<< uniform mwc
defaultMainWithIngredients ingredients $ bgroup "All"
[ bgroup "mwc"
-- One letter group names are used so they will fit on the plot.
Expand Down Expand Up @@ -148,6 +150,13 @@ main = do
bench "Double" $ whnfIO $ loop iter (M.random mtg :: IO Double)
, bench "Int" $ whnfIO $ loop iter (M.random mtg :: IO Int)
]
#if MIN_VERSION_random(1,3,0)
, bgroup "seed"
[ bench "SeedGen.fromSeed" $ let rseed = R.toSeed seed :: R.Seed Seed
in whnf R.fromSeed rseed
, bench "SeedGen.toSeed" $ whnf R.toSeed seed
]
#endif
]

betaBinomial :: StatefulGen g m => Double -> Double -> Int -> g -> m Int
Expand Down
18 changes: 16 additions & 2 deletions tests/props.hs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE ViewPatterns #-}
import Control.Monad
import Data.Word
Expand All @@ -16,6 +17,9 @@ import Test.QuickCheck.Monadic
import System.Random.MWC
import System.Random.MWC.Distributions
import System.Random.Stateful (StatefulGen)
#if MIN_VERSION_random(1,3,0)
import qualified System.Random.Stateful as Random (SeedGen(..))
#endif

----------------------------------------------------------------
--
Expand Down Expand Up @@ -65,6 +69,9 @@ main = do
g0 <- createSystemRandom
defaultMainWithIngredients ingredients $ testGroup "mwc"
[ testProperty "save/restore" $ prop_SeedSaveRestore g0
#if MIN_VERSION_random(1,3,0)
, testProperty "SeedGen" $ prop_SeedGen g0
#endif
, testCase "user save/restore" $ saveRestoreUserSeed
, testCase "empty seed data" $ emptySeed
, testCase "output correct" $ do
Expand All @@ -76,8 +83,7 @@ main = do
]

updateGenState :: GenIO -> IO ()
updateGenState g = replicateM_ 256 (uniform g :: IO Word32)

updateGenState g = replicateM_ 250 (uniform g :: IO Word32)

prop_SeedSaveRestore :: GenIO -> Property
prop_SeedSaveRestore g = monadicIO $ do
Expand All @@ -86,6 +92,14 @@ prop_SeedSaveRestore g = monadicIO $ do
seed' <- run $ save =<< restore seed
return $ seed == seed'

#if MIN_VERSION_random(1,3,0)
prop_SeedGen :: GenIO -> Property
prop_SeedGen g = monadicIO $ do
run $ updateGenState g
seed <- run $ save g
return $ seed == (Random.fromSeed . Random.toSeed) seed
#endif

saveRestoreUserSeed :: IO ()
saveRestoreUserSeed = do
let seed = toSeed $ U.replicate 258 0
Expand Down

0 comments on commit c134e61

Please sign in to comment.