module Data.Vector.Extended (
      fisherYatesShuffle
    , module Data.Vector
) where


import           Control.Monad.Primitive
import           Data.Foldable
import           Data.Vector
import qualified Data.Vector.Mutable     as VMut
import           System.Random.MWC



-- | Randomly permute a mutable 'Vector'.
--
-- You can use this via @'V.modify' 'fisherYatesShuffle'@ to permute an immutable vector.
fisherYatesShuffle
    :: PrimMonad f
    => Gen (PrimState f)
    -> MVector (PrimState f) a
    -> f ()
fisherYatesShuffle :: forall (f :: * -> *) a.
PrimMonad f =>
Gen (PrimState f) -> MVector (PrimState f) a -> f ()
fisherYatesShuffle Gen (PrimState f)
gen MVector (PrimState f) a
vec = do
    let n :: Int
n = MVector (PrimState f) a -> Int
forall s a. MVector s a -> Int
VMut.length MVector (PrimState f) a
vec
    [Int] -> (Int -> f ()) -> f ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Int
0..Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
2] ((Int -> f ()) -> f ()) -> (Int -> f ()) -> f ()
forall a b. (a -> b) -> a -> b
$ \Int
i -> do
        Int
j <- (Int, Int) -> Gen (PrimState f) -> f Int
forall a g (m :: * -> *).
(UniformRange a, StatefulGen g m) =>
(a, a) -> g -> m a
forall g (m :: * -> *). StatefulGen g m => (Int, Int) -> g -> m Int
uniformRM (Int
i, Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) Gen (PrimState f)
gen
        MVector (PrimState f) a -> Int -> Int -> f ()
forall (m :: * -> *) a.
PrimMonad m =>
MVector (PrimState m) a -> Int -> Int -> m ()
VMut.swap MVector (PrimState f) a
vec Int
i Int
j