packages feed

mini 1.6.2.0 → 1.6.3.0

raw patch · 4 files changed

+141/−1 lines, 4 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Mini.Random.Class: class Generator g => Splittable g
+ Mini.Random.Class: instance Mini.Random.Class.Generator Mini.Random.SplitMix.SplitMix
+ Mini.Random.Class: instance Mini.Random.Class.Splittable Mini.Random.SplitMix.SplitMix
+ Mini.Random.Class: split :: Splittable g => g -> (g, g)
+ Mini.Random.SplitMix: data SplitMix
+ Mini.Random.SplitMix: instance GHC.Classes.Eq Mini.Random.SplitMix.SplitMix
+ Mini.Random.SplitMix: instance GHC.Classes.Ord Mini.Random.SplitMix.SplitMix
+ Mini.Random.SplitMix: instance GHC.Show.Show Mini.Random.SplitMix.SplitMix
+ Mini.Random.SplitMix: nextWord32 :: SplitMix -> (Word32, SplitMix)
+ Mini.Random.SplitMix: nextWord64 :: SplitMix -> (Word64, SplitMix)
+ Mini.Random.SplitMix: seed :: Word64 -> SplitMix
+ Mini.Random.SplitMix: split :: SplitMix -> (SplitMix, SplitMix)

Files

CHANGELOG.md view
@@ -1,3 +1,12 @@+1.6.3.0 [2026-05-02]+--------------------+* Create Mini.Random.SplitMix: An implementation of SplitMix, based on+  <https://doi.org/10.1145/2660193.2660195>+* Mini.Random.Class:+  * Add class Splittable: The class of splittable generators+  * Add instance Generator SplitMix+  * Add instance Splittable SplitMix+ 1.6.2.0 [2026-05-01] -------------------- * Create Mini.Random.Class: A pure interface for pseudorandom value generation
mini.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               mini-version:            1.6.2.0+version:            1.6.3.0 license:            MIT license-file:       LICENSE author:             Victor Wallsten <victor.wallsten@protonmail.com>@@ -39,6 +39,7 @@     Mini.Hash.Murmur32     Mini.Optics.Lens     Mini.Random.Class+    Mini.Random.SplitMix     Mini.Transformers.Class     Mini.Transformers.EitherT     Mini.Transformers.MaybeT
src/Mini/Random/Class.hs view
@@ -5,6 +5,9 @@     nextWord32,     nextWord64   ),+  Splittable (+    split+  ),   Random (     random   ),@@ -43,6 +46,14 @@   add,   digest,  )+import Mini.Random.SplitMix (+  SplitMix,+ )+import qualified Mini.Random.SplitMix as SplitMix (+  nextWord32,+  nextWord64,+  split,+ ) import Prelude (   Bool,   Char,@@ -76,6 +87,17 @@         lo' = fromIntegral lo         hi' = fromIntegral hi `shiftL` 32      in (lo' .|. hi', g')++instance Generator SplitMix where+  nextWord32 = SplitMix.nextWord32+  nextWord64 = SplitMix.nextWord64++-- | The class of splittable pseudorandom number generators+class (Generator g) => Splittable g where+  split :: g -> (g, g)++instance Splittable SplitMix where+  split = SplitMix.split  -- | The class of types for which pseudorandom values can be generated class Random a where
+ src/Mini/Random/SplitMix.hs view
@@ -0,0 +1,108 @@+-- | An implementation of SplitMix: <https://doi.org/10.1145/2660193.2660195>+module Mini.Random.SplitMix (+  -- * Type+  SplitMix,++  -- * Construction+  seed,++  -- * Operations+  nextWord32,+  nextWord64,+  split,+) where++import Data.Bits (+  popCount,+  shiftR,+  xor,+  (.|.),+ )+import Data.Word (+  Word32,+  Word64,+ )+import Mini.Data.Recursion (+  bool,+ )+import Prelude (+  Eq,+  Ord,+  Show,+  fromIntegral,+  ($),+  (*),+  (+),+  (<),+ )++-- Type++-- | Abstract representation of a SplitMix generator+data SplitMix = SplitMix Word64 Word64+  deriving (Eq, Ord, Show)++-- Construction++-- | Make a generator from a seed+seed :: Word64 -> SplitMix+seed s = SplitMix (mix64 s) (mixGamma $ s + 0x9e3779b97f4a7c15)++-- Operations++-- | Generate the next 32-bit word+nextWord32 :: SplitMix -> (Word32, SplitMix)+nextWord32 (SplitMix s g) =+  let s' = s + g+   in (mix32 s', SplitMix s' g)++-- | Generate the next 64-bit word+nextWord64 :: SplitMix -> (Word64, SplitMix)+nextWord64 (SplitMix s g) =+  let s' = s + g+   in (mix64 s', SplitMix s' g)++-- | Split a generator into two (seemingly) independent generators+split :: SplitMix -> (SplitMix, SplitMix)+split (SplitMix s g) =+  let s' = s + g+      s'' = s' + g+      sm = SplitMix s'' g+      sm' = SplitMix (mix64 s') (mixGamma s'')+   in (sm, sm')++-- Helpers++mix64 :: Word64 -> Word64+mix64 z0 =+  let z1 = z0 `xor` (z0 `shiftR` 33)+      z2 = z1 * 0xff51afd7ed558ccd+      z3 = z2 `xor` (z2 `shiftR` 33)+      z4 = z3 * 0xc4ceb9fe1a85ec53+      z5 = z4 `xor` (z4 `shiftR` 33)+   in z5++mix32 :: Word64 -> Word32+mix32 z0 =+  let z1 = z0 `xor` (z0 `shiftR` 33)+      z2 = z1 * 0xff51afd7ed558ccd+      z3 = z2 `xor` (z2 `shiftR` 33)+      z4 = z3 * 0xc4ceb9fe1a85ec53+      z5 = z4 `shiftR` 32+   in fromIntegral z5++mix64variant13 :: Word64 -> Word64+mix64variant13 z0 =+  let z1 = z0 `xor` (z0 `shiftR` 30)+      z2 = z1 * 0xbf58476d1ce4e5b9+      z3 = z2 `xor` (z2 `shiftR` 27)+      z4 = z3 * 0x94d049bb133111eb+      z5 = z4 `xor` (z4 `shiftR` 31)+   in z5++mixGamma :: Word64 -> Word64+mixGamma z0 =+  let z1 = mix64variant13 z0 .|. 1+      n = popCount $ z1 `xor` (z1 `shiftR` 1)+   in -- based on the text on p. 466, not the code with inverted logic on p. 465+      bool z1 (z1 `xor` 0xaaaaaaaaaaaaaaaa) $ n < 24