    {-# LANGUAGE BangPatterns #-}
    {-# LANGUAGE CPP #-}
    {-# LANGUAGE MultiParamTypeClasses #-}
    {-# LANGUAGE TypeFamilies #-}
    -- |
    -- Module      : Data.Vector.Generic.Mutable.Base
    -- Copyright   : (c) Roman Leshchinskiy 2008-2011
    --                   Alexey Kuleshevich 2020-2022
    --                   Aleksey Khudyakov 2020-2022
    --                   Andrew Lelechenko 2020-2022
    -- License     : BSD-style
    --
    -- Maintainer  : Haskell Libraries Team <libraries@haskell.org>
    -- Stability   : experimental
    -- Portability : non-portable
    --
    -- Class of mutable vectors.

    module Data.Vector.Generic.Mutable.Base (
      MVector(..)
    ) where

    import Control.Monad.ST

    -- Data.Vector.Internal.Check is unused
    #define NOT_VECTOR_MODULE
    #include "vector.h"

    -- | Class of mutable vectors parameterised with a primitive state token.
    class MVector v a where
      -- | Length of the mutable vector. This method should not be
      -- called directly, use 'length' instead.
      basicLength       :: v s a -> Int

      -- | Yield a part of the mutable vector without copying it. This method
      -- should not be called directly, use 'unsafeSlice' instead.
      basicUnsafeSlice :: Int  -- ^ starting index
                       -> Int  -- ^ length of the slice
                       -> v s a
                       -> v s a

      -- | Check whether two vectors overlap. This method should not be
      -- called directly, use 'overlaps' instead.
      basicOverlaps    :: v s a -> v s a -> Bool

      -- | Create a mutable vector of the given length. This method should not be
      -- called directly, use 'unsafeNew' instead.
      basicUnsafeNew   :: Int -> ST s (v s a)

      -- | Initialize a vector to a standard value. This is intended to be called as
      -- part of the safe new operation (and similar operations), to properly blank
      -- the newly allocated memory if necessary.
      --
      -- Vectors that are necessarily initialized as part of creation may implement
      -- this as a no-op.
      --
      -- @since 0.11.0.0
      basicInitialize :: v s a -> ST s ()

      -- | Create a mutable vector of the given length and fill it with an
      -- initial value. This method should not be called directly, use
      -- 'replicate' instead.
      basicUnsafeReplicate :: Int -> a -> ST s (v s a)

      -- | Yield the element at the given position. This method should not be
      -- called directly, use 'unsafeRead' instead.
      basicUnsafeRead  :: v s a -> Int -> ST s a

      -- | Replace the element at the given position. This method should not be
      -- called directly, use 'unsafeWrite' instead.
      basicUnsafeWrite :: v s a -> Int -> a -> ST s ()

      -- | Reset all elements of the vector to some undefined value, clearing all
      -- references to external objects. This is usually a noop for unboxed
      -- vectors. This method should not be called directly, use 'clear' instead.
      basicClear       :: v s a -> ST s ()

      -- | Set all elements of the vector to the given value. This method should
      -- not be called directly, use 'set' instead.
      basicSet         :: v s a -> a -> ST s ()

      -- | Copy a vector. The two vectors may not overlap. This method should not
      -- be called directly, use 'unsafeCopy' instead.
      basicUnsafeCopy  :: v s a   -- ^ target
                       -> v s a   -- ^ source
                       -> ST s ()

      -- | Move the contents of a vector. The two vectors may overlap. This method
      -- should not be called directly, use 'unsafeMove' instead.
      basicUnsafeMove  :: v s a   -- ^ target
                       -> v s a   -- ^ source
                       -> ST s ()

      -- | Grow a vector by the given number of elements. Allocates a new vector and
      -- copies all of the elements over starting at 0 index. This method should not
      -- be called directly, use 'grow'\/'unsafeGrow' instead.
      basicUnsafeGrow  :: v s a -> Int -> ST s (v s a)

      {-# INLINE basicUnsafeReplicate #-}
      basicUnsafeReplicate Int
    n a
    x
        = do
            v <- Int -> ST s (v s a)
    forall s. Int -> ST s (v s a)
    forall (v :: * -> * -> *) a s. MVector v a => Int -> ST s (v s a)
    basicUnsafeNew Int
    n
            basicSet v x
            return v

      {-# INLINE basicClear #-}
      basicClear v s a
    _ = () -> ST s ()
    forall a. a -> ST s a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()

      {-# INLINE basicSet #-}
      basicSet !v s a
    v a
    x
        | Int
    n Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    0    = () -> ST s ()
    forall a. a -> ST s a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
        | Bool
    otherwise = do
                        v s a -> Int -> a -> ST s ()
    forall s. v s a -> Int -> a -> ST s ()
    forall (v :: * -> * -> *) a s.
    MVector v a =>
    v s a -> Int -> a -> ST s ()
    basicUnsafeWrite v s a
    v Int
    0 a
    x
                        Int -> ST s ()
    do_set Int
    1
        where
          !n :: Int
    n = v s a -> Int
    forall s. v s a -> Int
    forall (v :: * -> * -> *) a s. MVector v a => v s a -> Int
    basicLength v s a
    v

          do_set :: Int -> ST s ()
    do_set Int
    i | Int
    2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    i Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    n = do v s a -> v s a -> ST s ()
    forall s. v s a -> v s a -> ST s ()
    forall (v :: * -> * -> *) a s.
    MVector v a =>
    v s a -> v s a -> ST s ()
    basicUnsafeCopy (Int -> Int -> v s a -> v s a
    forall s. Int -> Int -> v s a -> v s a
    forall (v :: * -> * -> *) a s.
    MVector v a =>
    Int -> Int -> v s a -> v s a
    basicUnsafeSlice Int
    i Int
    i v s a
    v)
                                                  (Int -> Int -> v s a -> v s a
    forall s. Int -> Int -> v s a -> v s a
    forall (v :: * -> * -> *) a s.
    MVector v a =>
    Int -> Int -> v s a -> v s a
    basicUnsafeSlice Int
    0 Int
    i v s a
    v)
                                  Int -> ST s ()
    do_set (Int
    2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    i)
                   | Bool
    otherwise = v s a -> v s a -> ST s ()
    forall s. v s a -> v s a -> ST s ()
    forall (v :: * -> * -> *) a s.
    MVector v a =>
    v s a -> v s a -> ST s ()
    basicUnsafeCopy (Int -> Int -> v s a -> v s a
    forall s. Int -> Int -> v s a -> v s a
    forall (v :: * -> * -> *) a s.
    MVector v a =>
    Int -> Int -> v s a -> v s a
    basicUnsafeSlice Int
    i (Int
    nInt -> Int -> Int
    forall a. Num a => a -> a -> a
    -Int
    i) v s a
    v)
                                                 (Int -> Int -> v s a -> v s a
    forall s. Int -> Int -> v s a -> v s a
    forall (v :: * -> * -> *) a s.
    MVector v a =>
    Int -> Int -> v s a -> v s a
    basicUnsafeSlice Int
    0 (Int
    nInt -> Int -> Int
    forall a. Num a => a -> a -> a
    -Int
    i) v s a
    v)

      {-# INLINE basicUnsafeCopy #-}
      basicUnsafeCopy !v s a
    dst !v s a
    src = Int -> ST s ()
    do_copy Int
    0
        where
          !n :: Int
    n = v s a -> Int
    forall s. v s a -> Int
    forall (v :: * -> * -> *) a s. MVector v a => v s a -> Int
    basicLength v s a
    src

          do_copy :: Int -> ST s ()
    do_copy Int
    i | Int
    i Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    n = do
                                x <- v s a -> Int -> ST s a
    forall s. v s a -> Int -> ST s a
    forall (v :: * -> * -> *) a s.
    MVector v a =>
    v s a -> Int -> ST s a
    basicUnsafeRead v s a
    src Int
    i
                                basicUnsafeWrite dst i x
                                do_copy (i+1)
                    | Bool
    otherwise = () -> ST s ()
    forall a. a -> ST s a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()

      {-# INLINE basicUnsafeMove #-}
      basicUnsafeMove !v s a
    dst !v s a
    src
        | v s a -> v s a -> Bool
    forall s. v s a -> v s a -> Bool
    forall (v :: * -> * -> *) a s.
    MVector v a =>
    v s a -> v s a -> Bool
    basicOverlaps v s a
    dst v s a
    src = do
            srcCopy <- Int -> ST s (v s a)
    forall s. Int -> ST s (v s a)
    forall (v :: * -> * -> *) a s. MVector v a => Int -> ST s (v s a)
    basicUnsafeNew (v s a -> Int
    forall s. v s a -> Int
    forall (v :: * -> * -> *) a s. MVector v a => v s a -> Int
    basicLength v s a
    src)
            basicUnsafeCopy srcCopy src
            basicUnsafeCopy dst srcCopy
        | Bool
    otherwise = v s a -> v s a -> ST s ()
    forall s. v s a -> v s a -> ST s ()
    forall (v :: * -> * -> *) a s.
    MVector v a =>
    v s a -> v s a -> ST s ()
    basicUnsafeCopy v s a
    dst v s a
    src

      {-# INLINE basicUnsafeGrow #-}
      basicUnsafeGrow v s a
    v Int
    by
        = do
            v' <- Int -> ST s (v s a)
    forall s. Int -> ST s (v s a)
    forall (v :: * -> * -> *) a s. MVector v a => Int -> ST s (v s a)
    basicUnsafeNew (Int
    nInt -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    by)
            basicUnsafeCopy (basicUnsafeSlice 0 n v') v
            return v'
        where
          n :: Int
    n = v s a -> Int
    forall s. v s a -> Int
    forall (v :: * -> * -> *) a s. MVector v a => v s a -> Int
    basicLength v s a
    v

      {-# MINIMAL basicLength, basicUnsafeSlice, basicOverlaps,
                  basicUnsafeNew, basicInitialize, basicUnsafeRead,
                  basicUnsafeWrite #-}