{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
-- |
-- Module      : Data.Massiv.Core.Common
-- Copyright   : (c) Alexey Kuleshevich 2018-2021
-- License     : BSD3
-- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>
-- Stability   : experimental
-- Portability : non-portable
module Data.Massiv.Core.Common
  ( Array
  , Vector
  , MVector
  , Matrix
  , MMatrix
  , Elt
  , Steps(..)
  , Stream(..)
  , Construct(..)
  , Source(..)
  , Load(..)
  , StrideLoad(..)
  , Resize(..)
  , Extract(..)
  , Slice(..)
  , OuterSlice(..)
  , InnerSlice(..)
  , Manifest(..)
  , Mutable(..)
  , Comp(..)
  , Scheduler
  , numWorkers
  , scheduleWork
  , scheduleWork_
  , withMassivScheduler_
  , WorkerStates
  , unsafeRead
  , unsafeWrite
  , unsafeModify
  , unsafeLinearModify
  , unsafeSwap
  , unsafeLinearSwap
  , unsafeDefaultLinearShrink
  , Ragged(..)
  , Nested(..)
  , NestedStruct
  , empty
  , singleton
  -- * Size
  , elemsCount
  , linearSize
  , isNotEmpty
  , Sz(SafeSz)
  , Size(..)
  -- * Indexing
  , (!?)
  , index
  , indexM
  , (!)
  , index'
  , (??)
  , defaultIndex
  , borderIndex
  , evaluateM
  , evaluate'
  , module Data.Massiv.Core.Index
  -- * Common Operations
  , imapM_
  , Semigroup((<>))
  -- * Exceptions
  , MonadThrow(..)
  , throw
  , IndexException(..)
  , SizeException(..)
  , ShapeException(..)
  , module Data.Massiv.Core.Exception
  , Proxy(..)
  , Id(..)
  -- * Stateful Monads
  , runST
  , ST
  , MonadUnliftIO
  , MonadIO(liftIO)
  , PrimMonad(PrimState)
  ) where

#if !MIN_VERSION_base(4,11,0)
import Data.Semigroup
#endif
import Control.Exception (throw)
import Control.Monad.Catch (MonadThrow(..))
import Control.Monad.IO.Unlift (MonadIO(liftIO), MonadUnliftIO)
import Control.Monad.Primitive
import Control.Monad.ST
import Control.Scheduler (Comp(..), Scheduler, WorkerStates, numWorkers,
                          scheduleWork, scheduleWork_, withScheduler_, trivialScheduler_)
import Control.Scheduler.Global
import Data.Massiv.Core.Exception
import Data.Massiv.Core.Index
import Data.Massiv.Core.Index.Internal (Sz(SafeSz))
import Data.Typeable
import Data.Vector.Fusion.Bundle.Size
import qualified Data.Vector.Fusion.Stream.Monadic as S (Stream)
import Data.Vector.Fusion.Util

#include "massiv.h"

-- | The array family. Representations @r@ describe how data is arranged or computed. All
-- arrays have a common property that each index @ix@ always maps to the same unique
-- element, even if that element does not yet exist in memory and the arry has to be
-- computed in order to get access to that element. Data is always arranged in a nested
-- row-major fashion, depth of which is controlled by @`Rank` ix@.
data family Array r ix e :: *

-- | Type synonym for a single dimension array, or simply a flat vector.
--
-- @since 0.5.0
type Vector r e = Array r Ix1 e


-- | Type synonym for a single dimension mutable array, or simply a flat mutable vector.
--
-- @since 0.5.0
type MVector s r e = MArray s r Ix1 e

-- | Type synonym for a two-dimentsional array, or simply a matrix.
--
-- @since 0.5.0
type Matrix r e = Array r Ix2 e


-- | Type synonym for a two-dimentsional mutable array, or simply a mutable matrix.
--
-- @since 0.5.0
type MMatrix s r e = MArray s r Ix2 e



type family Elt r ix e :: * where
  Elt r Ix1 e = e
  Elt r ix  e = Array (R r) (Lower ix) e

type family NestedStruct r ix e :: *



class Load r ix e => Stream r ix e where
  toStream :: Array r ix e -> Steps Id e

  toStreamIx :: Array r ix e -> Steps Id (ix, e)

data Steps m e = Steps
  { Steps m e -> Stream m e
stepsStream :: S.Stream m e
  , Steps m e -> Size
stepsSize   :: Size
  }


-- | Array types that can be constructed.
class (Typeable r, Index ix) => Construct r ix e where
  {-# MINIMAL setComp,(makeArray|makeArrayLinear) #-}

  -- | Set computation strategy for this array
  --
  -- ==== __Example__
  --
  -- >>> :set -XTypeApplications
  -- >>> import Data.Massiv.Array
  -- >>> a = singleton @DL @Ix1 @Int 0
  -- >>> a
  -- Array DL Seq (Sz1 1)
  --   [ 0 ]
  -- >>> setComp (ParN 6) a -- use 6 capabilities
  -- Array DL (ParN 6) (Sz1 1)
  --   [ 0 ]
  --
  setComp :: Comp -> Array r ix e -> Array r ix e

  -- | Construct an Array. Resulting type either has to be unambiguously inferred or restricted
  -- manually, like in the example below. Use "Data.Massiv.Array.makeArrayR" if you'd like to
  -- specify representation as an argument.
  --
  -- >>> import Data.Massiv.Array
  -- >>> makeArray Seq (Sz (3 :. 4)) (\ (i :. j) -> if i == j then i else 0) :: Array D Ix2 Int
  -- Array D Seq (Sz (3 :. 4))
  --   [ [ 0, 0, 0, 0 ]
  --   , [ 0, 1, 0, 0 ]
  --   , [ 0, 0, 2, 0 ]
  --   ]
  --
  -- Instead of restricting the full type manually we can use `TypeApplications` as convenience:
  --
  -- >>> :set -XTypeApplications
  -- >>> makeArray @P @_ @Double Seq (Sz2 3 4) $ \(i :. j) -> logBase (fromIntegral i) (fromIntegral j)
  -- Array P Seq (Sz (3 :. 4))
  --   [ [ NaN, -0.0, -0.0, -0.0 ]
  --   , [ -Infinity, NaN, Infinity, Infinity ]
  --   , [ -Infinity, 0.0, 1.0, 1.5849625007211563 ]
  --   ]
  --
  -- @since 0.1.0
  makeArray ::
       Comp -- ^ Computation strategy. Useful constructors are `Seq` and `Par`
    -> Sz ix -- ^ Size of the result array.
    -> (ix -> e) -- ^ Function to generate elements at a particular index
    -> Array r ix e
  makeArray Comp
comp Sz ix
sz ix -> e
f = Comp -> Sz ix -> (Int -> e) -> Array r ix e
forall r ix e.
Construct r ix e =>
Comp -> Sz ix -> (Int -> e) -> Array r ix e
makeArrayLinear Comp
comp Sz ix
sz (ix -> e
f (ix -> e) -> (Int -> ix) -> Int -> e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sz ix -> Int -> ix
forall ix. Index ix => Sz ix -> Int -> ix
fromLinearIndex Sz ix
sz)
  {-# INLINE makeArray #-}

  -- | Same as `makeArray`, but produce elements using linear row-major index.
  --
  -- >>> import Data.Massiv.Array
  -- >>> makeArrayLinear Seq (Sz (2 :. 4)) id :: Array D Ix2 Int
  -- Array D Seq (Sz (2 :. 4))
  --   [ [ 0, 1, 2, 3 ]
  --   , [ 4, 5, 6, 7 ]
  --   ]
  --
  -- @since 0.3.0
  makeArrayLinear :: Comp -> Sz ix -> (Int -> e) -> Array r ix e
  makeArrayLinear Comp
comp Sz ix
sz Int -> e
f = Comp -> Sz ix -> (ix -> e) -> Array r ix e
forall r ix e.
Construct r ix e =>
Comp -> Sz ix -> (ix -> e) -> Array r ix e
makeArray Comp
comp Sz ix
sz (Int -> e
f (Int -> e) -> (ix -> Int) -> ix -> e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sz ix -> ix -> Int
forall ix. Index ix => Sz ix -> ix -> Int
toLinearIndex Sz ix
sz)
  {-# INLINE makeArrayLinear #-}

  replicate :: Comp -> Sz ix -> e -> Array r ix e
  replicate Comp
comp Sz ix
sz !e
e = Comp -> Sz ix -> (ix -> e) -> Array r ix e
forall r ix e.
Construct r ix e =>
Comp -> Sz ix -> (ix -> e) -> Array r ix e
makeArray Comp
comp Sz ix
sz (e -> ix -> e
forall a b. a -> b -> a
const e
e)
  {-# INLINE replicate #-}

class Index ix => Resize r ix where
  -- | /O(1)/ - Change the size of an array. Total number of elements should be the same, but it is
  -- not validated.
  unsafeResize :: Index ix' => Sz ix' -> Array r ix e -> Array r ix' e


class Load r ix e => Extract r ix e where
  -- | /O(1)/ - Extract a portion of an array. Staring index and new size are
  -- not validated.
  unsafeExtract :: ix -> Sz ix -> Array r ix e -> Array (R r) ix e


-- | Arrays that can be used as source to practically any manipulation function.
class (Resize r ix, Load r ix e) => Source r ix e where
  {-# MINIMAL (unsafeIndex|unsafeLinearIndex), unsafeLinearSlice #-}

  -- | Lookup element in the array. No bounds check is performed and access of
  -- arbitrary memory is possible when invalid index is supplied.
  --
  -- @since 0.1.0
  unsafeIndex :: Array r ix e -> ix -> e
  unsafeIndex =
    INDEX_CHECK("(Source r ix e).unsafeIndex",
                size, \ !arr -> unsafeLinearIndex arr . toLinearIndex (size arr))
  {-# INLINE unsafeIndex #-}

  -- | Lookup element in the array using flat index in a row-major fashion. No
  -- bounds check is performed
  --
  -- @since 0.1.0
  unsafeLinearIndex :: Array r ix e -> Int -> e
  unsafeLinearIndex !Array r ix e
arr = Array r ix e -> ix -> e
forall r ix e. Source r ix e => Array r ix e -> ix -> e
unsafeIndex Array r ix e
arr (ix -> e) -> (Int -> ix) -> Int -> e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sz ix -> Int -> ix
forall ix. Index ix => Sz ix -> Int -> ix
fromLinearIndex (Array r ix e -> Sz ix
forall r ix e. Load r ix e => Array r ix e -> Sz ix
size Array r ix e
arr)
  {-# INLINE unsafeLinearIndex #-}

  -- | /O(1)/ - Source arrays also give us ability to look at their linear slices in
  -- constant time
  --
  -- @since 0.5.0
  unsafeLinearSlice :: Ix1 -> Sz1 -> Array r ix e -> Array r Ix1 e

-- | Any array that can be computed and loaded into memory
class (Typeable r, Index ix) => Load r ix e where
  type family R r :: *
  type instance R r = r
  {-# MINIMAL getComp, size, (loadArrayM | loadArrayWithSetM) #-}

  -- | Get computation strategy of this array
  --
  -- @since 0.1.0
  getComp :: Array r ix e -> Comp

  -- | Get the exact size of an immutabe array. Most of the time will produce the size in
  -- constant time, except for `DS` representation, which could result in evaluation of
  -- the whole stream. See `maxSize` and `Data.Massiv.Vector.slength` for more info.
  --
  -- @since 0.1.0
  size :: Array r ix e -> Sz ix

  -- | Load an array into memory.
  --
  -- @since 0.3.0
  loadArrayM
    :: Monad m =>
       Scheduler m ()
    -> Array r ix e -- ^ Array that is being loaded
    -> (Int -> e -> m ()) -- ^ Function that writes an element into target array
    -> m ()
  loadArrayM Scheduler m ()
scheduler Array r ix e
arr Int -> e -> m ()
uWrite =
    Scheduler m ()
-> Array r ix e
-> (Int -> e -> m ())
-> (Int -> Sz1 -> e -> m ())
-> m ()
forall r ix e (m :: * -> *).
(Load r ix e, Monad m) =>
Scheduler m ()
-> Array r ix e
-> (Int -> e -> m ())
-> (Int -> Sz1 -> e -> m ())
-> m ()
loadArrayWithSetM Scheduler m ()
scheduler Array r ix e
arr Int -> e -> m ()
uWrite ((Int -> Sz1 -> e -> m ()) -> m ())
-> (Int -> Sz1 -> e -> m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ \Int
offset Sz1
sz e
e ->
      Int -> (Int -> Bool) -> (Int -> Int) -> (Int -> m ()) -> m ()
forall (m :: * -> *) a.
Monad m =>
Int -> (Int -> Bool) -> (Int -> Int) -> (Int -> m a) -> m ()
loopM_ Int
offset (Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< (Int
offset Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Sz1 -> Int
forall ix. Sz ix -> ix
unSz Sz1
sz)) (Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) (\Int
i -> Int -> e -> m ()
uWrite Int
i e
e)
  {-# INLINE loadArrayM #-}

  -- | Load an array into memory, just like `loadArrayM`. Except it also accepts a
  -- function that is potentially optimized for setting many cells in a region to the same
  -- value
  --
  -- @since 0.5.8
  loadArrayWithSetM
    :: Monad m =>
       Scheduler m ()
    -> Array r ix e -- ^ Array that is being loaded
    -> (Ix1 -> e -> m ()) -- ^ Function that writes an element into target array
    -> (Ix1 -> Sz1 -> e -> m ()) -- ^ Function that efficiently sets a region of an array
                                 -- to the supplied value target array
    -> m ()
  loadArrayWithSetM Scheduler m ()
scheduler Array r ix e
arr Int -> e -> m ()
uWrite Int -> Sz1 -> e -> m ()
_ = Scheduler m () -> Array r ix e -> (Int -> e -> m ()) -> m ()
forall r ix e (m :: * -> *).
(Load r ix e, Monad m) =>
Scheduler m () -> Array r ix e -> (Int -> e -> m ()) -> m ()
loadArrayM Scheduler m ()
scheduler Array r ix e
arr Int -> e -> m ()
uWrite
  {-# INLINE loadArrayWithSetM #-}

  -- | /O(1)/ - Get the possible maximum size of an immutabe array. If the lookup of size
  -- in constant time is not possible, `Nothing` will be returned. This value will be used
  -- as the initial size of the mutable array into which the loading will happen.
  --
  -- @since 0.5.0
  maxSize :: Array r ix e -> Maybe (Sz ix)
  maxSize = Sz ix -> Maybe (Sz ix)
forall a. a -> Maybe a
Just (Sz ix -> Maybe (Sz ix))
-> (Array r ix e -> Sz ix) -> Array r ix e -> Maybe (Sz ix)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Array r ix e -> Sz ix
forall r ix e. Load r ix e => Array r ix e -> Sz ix
size
  {-# INLINE maxSize #-}


  -- | /O(1)/ - Check if an array has no elements.
  --
  -- ==== __Examples__
  --
  -- >>> import Data.Massiv.Array
  -- >>> isEmpty $ range Seq (Ix2 10 20) (11 :. 21)
  -- False
  -- >>> isEmpty $ range Seq (Ix2 10 20) (10 :. 21)
  -- True
  --
  -- @since 0.1.0
  isEmpty :: Array r ix e -> Bool
  isEmpty !Array r ix e
arr = Int
0 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Array r ix e -> Int
forall r ix e. Load r ix e => Array r ix e -> Int
elemsCount Array r ix e
arr
  {-# INLINE isEmpty #-}


  -- | Load into a supplied mutable array sequentially. Returned array does not have to be
  -- the same
  --
  -- @since 0.5.7
  unsafeLoadIntoS ::
       (Mutable r' ix e, PrimMonad m)
    => MArray (PrimState m) r' ix e
    -> Array r ix e
    -> m (MArray (PrimState m) r' ix e)
  unsafeLoadIntoS MArray (PrimState m) r' ix e
marr Array r ix e
arr =
    MArray (PrimState m) r' ix e
marr MArray (PrimState m) r' ix e
-> m () -> m (MArray (PrimState m) r' ix e)
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Scheduler m ()
-> Array r ix e
-> (Int -> e -> m ())
-> (Int -> Sz1 -> e -> m ())
-> m ()
forall r ix e (m :: * -> *).
(Load r ix e, Monad m) =>
Scheduler m ()
-> Array r ix e
-> (Int -> e -> m ())
-> (Int -> Sz1 -> e -> m ())
-> m ()
loadArrayWithSetM Scheduler m ()
forall (f :: * -> *). Applicative f => Scheduler f ()
trivialScheduler_ Array r ix e
arr (MArray (PrimState m) r' ix e -> Int -> e -> m ()
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
MArray (PrimState m) r ix e -> Int -> e -> m ()
unsafeLinearWrite MArray (PrimState m) r' ix e
marr) (MArray (PrimState m) r' ix e -> Int -> Sz1 -> e -> m ()
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
MArray (PrimState m) r ix e -> Int -> Sz1 -> e -> m ()
unsafeLinearSet MArray (PrimState m) r' ix e
marr)
  {-# INLINE unsafeLoadIntoS #-}

  -- | Same as `unsafeLoadIntoS`, but respecting computation strategy.
  --
  -- @since 0.5.7
  unsafeLoadIntoM ::
       (Mutable r' ix e, MonadIO m)
    => MArray RealWorld r' ix e
    -> Array r ix e
    -> m (MArray RealWorld r' ix e)
  unsafeLoadIntoM MArray RealWorld r' ix e
marr Array r ix e
arr = do
    IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ Comp -> (Scheduler IO () -> IO ()) -> IO ()
withMassivScheduler_ (Array r ix e -> Comp
forall r ix e. Load r ix e => Array r ix e -> Comp
getComp Array r ix e
arr) ((Scheduler IO () -> IO ()) -> IO ())
-> (Scheduler IO () -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Scheduler IO ()
scheduler ->
      Scheduler IO ()
-> Array r ix e
-> (Int -> e -> IO ())
-> (Int -> Sz1 -> e -> IO ())
-> IO ()
forall r ix e (m :: * -> *).
(Load r ix e, Monad m) =>
Scheduler m ()
-> Array r ix e
-> (Int -> e -> m ())
-> (Int -> Sz1 -> e -> m ())
-> m ()
loadArrayWithSetM Scheduler IO ()
scheduler Array r ix e
arr (MArray (PrimState IO) r' ix e -> Int -> e -> IO ()
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
MArray (PrimState m) r ix e -> Int -> e -> m ()
unsafeLinearWrite MArray RealWorld r' ix e
MArray (PrimState IO) r' ix e
marr) (MArray (PrimState IO) r' ix e -> Int -> Sz1 -> e -> IO ()
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
MArray (PrimState m) r ix e -> Int -> Sz1 -> e -> m ()
unsafeLinearSet MArray RealWorld r' ix e
MArray (PrimState IO) r' ix e
marr)
    MArray RealWorld r' ix e -> m (MArray RealWorld r' ix e)
forall (f :: * -> *) a. Applicative f => a -> f a
pure MArray RealWorld r' ix e
marr
  {-# INLINE unsafeLoadIntoM #-}


-- | Selects an optimal scheduler for the supplied strategy, but it works only in `IO`
withMassivScheduler_ :: Comp -> (Scheduler IO () -> IO ()) -> IO ()
withMassivScheduler_ :: Comp -> (Scheduler IO () -> IO ()) -> IO ()
withMassivScheduler_ Comp
comp Scheduler IO () -> IO ()
f =
  case Comp
comp of
    Comp
Par -> GlobalScheduler IO -> (Scheduler IO () -> IO ()) -> IO ()
forall (m :: * -> *) a.
MonadUnliftIO m =>
GlobalScheduler m -> (Scheduler m () -> m a) -> m ()
withGlobalScheduler_ GlobalScheduler IO
globalScheduler Scheduler IO () -> IO ()
f
    Comp
Seq -> Scheduler IO () -> IO ()
f Scheduler IO ()
forall (f :: * -> *). Applicative f => Scheduler f ()
trivialScheduler_
    Comp
_ -> Comp -> (Scheduler IO () -> IO ()) -> IO ()
forall (m :: * -> *) a b.
MonadUnliftIO m =>
Comp -> (Scheduler m a -> m b) -> m ()
withScheduler_ Comp
comp Scheduler IO () -> IO ()
f

class Load r ix e => StrideLoad r ix e where
  -- | Load an array into memory with stride. Default implementation requires an instance of
  -- `Source`.
  loadArrayWithStrideM
    :: Monad m =>
       Scheduler m ()
    -> Stride ix -- ^ Stride to use
    -> Sz ix -- ^ Size of the target array affected by the stride.
    -> Array r ix e -- ^ Array that is being loaded
    -> (Int -> e -> m ()) -- ^ Function that writes an element into target array
    -> m ()
  default loadArrayWithStrideM
    :: (Source r ix e, Monad m) =>
       Scheduler m ()
    -> Stride ix
    -> Sz ix
    -> Array r ix e
    -> (Int -> e -> m ())
    -> m ()
  loadArrayWithStrideM Scheduler m ()
scheduler Stride ix
stride Sz ix
resultSize Array r ix e
arr =
    Scheduler m () -> Int -> (Int -> e) -> (Int -> e -> m ()) -> m ()
forall (m :: * -> *) b.
Monad m =>
Scheduler m () -> Int -> (Int -> b) -> (Int -> b -> m ()) -> m ()
splitLinearlyWith_ Scheduler m ()
scheduler (Sz ix -> Int
forall ix. Index ix => Sz ix -> Int
totalElem Sz ix
resultSize) Int -> e
unsafeLinearWriteWithStride
    where
      !strideIx :: ix
strideIx = Stride ix -> ix
forall ix. Stride ix -> ix
unStride Stride ix
stride
      unsafeLinearWriteWithStride :: Int -> e
unsafeLinearWriteWithStride =
        Array r ix e -> ix -> e
forall r ix e. Source r ix e => Array r ix e -> ix -> e
unsafeIndex Array r ix e
arr (ix -> e) -> (Int -> ix) -> Int -> e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Int -> Int) -> ix -> ix -> ix
forall ix. Index ix => (Int -> Int -> Int) -> ix -> ix -> ix
liftIndex2 Int -> Int -> Int
forall a. Num a => a -> a -> a
(*) ix
strideIx (ix -> ix) -> (Int -> ix) -> Int -> ix
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sz ix -> Int -> ix
forall ix. Index ix => Sz ix -> Int -> ix
fromLinearIndex Sz ix
resultSize
      {-# INLINE unsafeLinearWriteWithStride #-}
  {-# INLINE loadArrayWithStrideM #-}


class Load r ix e => OuterSlice r ix e where
  -- | /O(1)/ - Take a slice out of an array from the outside
  unsafeOuterSlice :: Array r ix e -> Int -> Elt r ix e

class Load r ix e => InnerSlice r ix e where
  unsafeInnerSlice :: Array r ix e -> (Sz (Lower ix), Sz Int) -> Int -> Elt r ix e

class Load r ix e => Slice r ix e where
  unsafeSlice :: MonadThrow m => Array r ix e -> ix -> Sz ix -> Dim -> m (Elt r ix e)


-- | Manifest arrays are backed by actual memory and values are looked up versus
-- computed as it is with delayed arrays. Because of this fact indexing functions
-- @(`!`)@, @(`!?`)@, etc. are constrained to manifest arrays only.
class Source r ix e => Manifest r ix e where

  unsafeLinearIndexM :: Array r ix e -> Int -> e


class (Construct r ix e, Manifest r ix e) => Mutable r ix e where
  data MArray s r ix e :: *

  -- | Get the size of a mutable array.
  --
  -- @since 0.1.0
  msize :: MArray s r ix e -> Sz ix

  -- | Convert immutable array into a mutable array without copy.
  --
  -- @since 0.1.0
  unsafeThaw :: PrimMonad m => Array r ix e -> m (MArray (PrimState m) r ix e)

  -- | Convert mutable array into an immutable array without copy.
  --
  -- @since 0.1.0
  unsafeFreeze :: PrimMonad m => Comp -> MArray (PrimState m) r ix e -> m (Array r ix e)

  -- | Create new mutable array, leaving it's elements uninitialized. Size isn't validated either.
  --
  -- @since 0.1.0
  unsafeNew :: PrimMonad m => Sz ix -> m (MArray (PrimState m) r ix e)

  -- | Read an element at linear row-major index
  --
  -- @since 0.1.0
  unsafeLinearRead :: PrimMonad m => MArray (PrimState m) r ix e -> Int -> m e

  -- | Write an element into mutable array with linear row-major index
  --
  -- @since 0.1.0
  unsafeLinearWrite :: PrimMonad m => MArray (PrimState m) r ix e -> Int -> e -> m ()

  -- | Initialize mutable array to some default value.
  --
  -- @since 0.3.0
  initialize :: PrimMonad m => MArray (PrimState m) r ix e -> m ()

  -- | Create new mutable array while initializing all elements to some default value.
  --
  -- @since 0.3.0
  initializeNew :: PrimMonad m => Maybe e -> Sz ix -> m (MArray (PrimState m) r ix e)
  initializeNew Maybe e
Nothing Sz ix
sz = Sz ix -> m (MArray (PrimState m) r ix e)
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
Sz ix -> m (MArray (PrimState m) r ix e)
unsafeNew Sz ix
sz m (MArray (PrimState m) r ix e)
-> (MArray (PrimState m) r ix e -> m (MArray (PrimState m) r ix e))
-> m (MArray (PrimState m) r ix e)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \MArray (PrimState m) r ix e
ma -> MArray (PrimState m) r ix e
ma MArray (PrimState m) r ix e
-> m () -> m (MArray (PrimState m) r ix e)
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ MArray (PrimState m) r ix e -> m ()
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
MArray (PrimState m) r ix e -> m ()
initialize MArray (PrimState m) r ix e
ma
  initializeNew (Just e
e) Sz ix
sz = Sz ix -> e -> m (MArray (PrimState m) r ix e)
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
Sz ix -> e -> m (MArray (PrimState m) r ix e)
newMArray Sz ix
sz e
e
  {-# INLINE initializeNew #-}

  -- | Create new mutable array while initializing all elements to the specified value.
  --
  -- @since 0.6.0
  newMArray :: PrimMonad m => Sz ix -> e -> m (MArray (PrimState m) r ix e)
  newMArray Sz ix
sz e
e = do
    MArray (PrimState m) r ix e
marr <- Sz ix -> m (MArray (PrimState m) r ix e)
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
Sz ix -> m (MArray (PrimState m) r ix e)
unsafeNew Sz ix
sz
    MArray (PrimState m) r ix e
marr MArray (PrimState m) r ix e
-> m () -> m (MArray (PrimState m) r ix e)
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ MArray (PrimState m) r ix e -> Int -> Sz1 -> e -> m ()
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
MArray (PrimState m) r ix e -> Int -> Sz1 -> e -> m ()
unsafeLinearSet MArray (PrimState m) r ix e
marr Int
0 (Int -> Sz1
forall ix. ix -> Sz ix
SafeSz (Sz ix -> Int
forall ix. Index ix => Sz ix -> Int
totalElem Sz ix
sz)) e
e
  {-# INLINE newMArray #-}

  -- | Set all cells in the mutable array within the range to a specified value.
  --
  -- @since 0.3.0
  unsafeLinearSet :: PrimMonad m =>
                     MArray (PrimState m) r ix e -> Ix1 -> Sz1 -> e -> m ()
  unsafeLinearSet MArray (PrimState m) r ix e
marr Int
offset Sz1
len e
e =
    Int -> (Int -> Bool) -> (Int -> Int) -> (Int -> m ()) -> m ()
forall (m :: * -> *) a.
Monad m =>
Int -> (Int -> Bool) -> (Int -> Int) -> (Int -> m a) -> m ()
loopM_ Int
offset (Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< (Int
offset Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Sz1 -> Int
forall ix. Sz ix -> ix
unSz Sz1
len)) (Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) (\Int
i -> MArray (PrimState m) r ix e -> Int -> e -> m ()
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
MArray (PrimState m) r ix e -> Int -> e -> m ()
unsafeLinearWrite MArray (PrimState m) r ix e
marr Int
i e
e)
  {-# INLINE unsafeLinearSet #-}

  -- | Copy part of one mutable array into another
  --
  -- @since 0.3.6
  unsafeLinearCopy :: (Mutable r ix' e, PrimMonad m) =>
                      MArray (PrimState m) r ix' e -- ^ Source mutable array
                   -> Ix1 -- ^ Starting index at source array
                   -> MArray (PrimState m) r ix e -- ^ Target mutable array
                   -> Ix1 -- ^ Starting index at target array
                   -> Sz1 -- ^ Number of elements to copy
                   -> m ()
  unsafeLinearCopy MArray (PrimState m) r ix' e
marrFrom Int
iFrom MArray (PrimState m) r ix e
marrTo Int
iTo (SafeSz Int
k) = do
    let delta :: Int
delta = Int
iTo Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
iFrom
    Int -> (Int -> Bool) -> (Int -> Int) -> (Int -> m ()) -> m ()
forall (m :: * -> *) a.
Monad m =>
Int -> (Int -> Bool) -> (Int -> Int) -> (Int -> m a) -> m ()
loopM_ Int
iFrom (Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
iFrom) (Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) ((Int -> m ()) -> m ()) -> (Int -> m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ \Int
i ->
      MArray (PrimState m) r ix' e -> Int -> m e
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
MArray (PrimState m) r ix e -> Int -> m e
unsafeLinearRead MArray (PrimState m) r ix' e
marrFrom Int
i m e -> (e -> m ()) -> m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= MArray (PrimState m) r ix e -> Int -> e -> m ()
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
MArray (PrimState m) r ix e -> Int -> e -> m ()
unsafeLinearWrite MArray (PrimState m) r ix e
marrTo (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
delta)
  {-# INLINE unsafeLinearCopy #-}

  -- | Copy a part of a pure array into a mutable array
  --
  -- @since 0.3.6
  unsafeArrayLinearCopy :: (Mutable r ix' e, PrimMonad m) =>
                           Array r ix' e -- ^ Source pure array
                        -> Ix1 -- ^ Starting index at source array
                        -> MArray (PrimState m) r ix e -- ^ Target mutable array
                        -> Ix1 -- ^ Starting index at target array
                        -> Sz1 -- ^ Number of elements to copy
                        -> m ()
  unsafeArrayLinearCopy Array r ix' e
arrFrom Int
iFrom MArray (PrimState m) r ix e
marrTo Int
iTo (SafeSz Int
k) = do
    let delta :: Int
delta = Int
iTo Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
iFrom
    Int -> (Int -> Bool) -> (Int -> Int) -> (Int -> m ()) -> m ()
forall (m :: * -> *) a.
Monad m =>
Int -> (Int -> Bool) -> (Int -> Int) -> (Int -> m a) -> m ()
loopM_ Int
iFrom (Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
iFrom) (Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) ((Int -> m ()) -> m ()) -> (Int -> m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ \Int
i ->
      MArray (PrimState m) r ix e -> Int -> e -> m ()
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
MArray (PrimState m) r ix e -> Int -> e -> m ()
unsafeLinearWrite MArray (PrimState m) r ix e
marrTo (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
delta) (Array r ix' e -> Int -> e
forall r ix e. Source r ix e => Array r ix e -> Int -> e
unsafeLinearIndex Array r ix' e
arrFrom Int
i)
  {-# INLINE unsafeArrayLinearCopy #-}

  -- | Linearly reduce the size of an array. Total number of elements should be smaller or
  -- equal. There is no guarantee that the original array is left unchanged, so it should
  -- no longer be used.
  --
  -- @since 0.3.6
  unsafeLinearShrink :: PrimMonad m =>
                        MArray (PrimState m) r ix e -> Sz ix -> m (MArray (PrimState m) r ix e)
  unsafeLinearShrink = MArray (PrimState m) r ix e
-> Sz ix -> m (MArray (PrimState m) r ix e)
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
MArray (PrimState m) r ix e
-> Sz ix -> m (MArray (PrimState m) r ix e)
unsafeDefaultLinearShrink
  {-# INLINE unsafeLinearShrink #-}

  -- | Linearly increase the size of an array. Total number of elements should be larger
  -- or equal. There is no guarantee that the original array is left unchanged, so it
  -- should no longer be used.
  --
  -- @since 0.3.6
  unsafeLinearGrow :: PrimMonad m =>
                      MArray (PrimState m) r ix e -> Sz ix -> m (MArray (PrimState m) r ix e)
  unsafeLinearGrow MArray (PrimState m) r ix e
marr Sz ix
sz = do
    MArray (PrimState m) r ix e
marr' <- Sz ix -> m (MArray (PrimState m) r ix e)
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
Sz ix -> m (MArray (PrimState m) r ix e)
unsafeNew Sz ix
sz
    MArray (PrimState m) r ix e
-> Int -> MArray (PrimState m) r ix e -> Int -> Sz1 -> m ()
forall r ix e ix' (m :: * -> *).
(Mutable r ix e, Mutable r ix' e, PrimMonad m) =>
MArray (PrimState m) r ix' e
-> Int -> MArray (PrimState m) r ix e -> Int -> Sz1 -> m ()
unsafeLinearCopy MArray (PrimState m) r ix e
marr Int
0 MArray (PrimState m) r ix e
marr' Int
0 (Sz1 -> m ()) -> Sz1 -> m ()
forall a b. (a -> b) -> a -> b
$ Int -> Sz1
forall ix. ix -> Sz ix
SafeSz (Sz ix -> Int
forall ix. Index ix => Sz ix -> Int
totalElem (MArray (PrimState m) r ix e -> Sz ix
forall r ix e s. Mutable r ix e => MArray s r ix e -> Sz ix
msize MArray (PrimState m) r ix e
marr))
    MArray (PrimState m) r ix e -> m (MArray (PrimState m) r ix e)
forall (f :: * -> *) a. Applicative f => a -> f a
pure MArray (PrimState m) r ix e
marr'
  {-# INLINE unsafeLinearGrow #-}


unsafeDefaultLinearShrink ::
     (Mutable r ix e, PrimMonad m)
  => MArray (PrimState m) r ix e
  -> Sz ix
  -> m (MArray (PrimState m) r ix e)
unsafeDefaultLinearShrink :: MArray (PrimState m) r ix e
-> Sz ix -> m (MArray (PrimState m) r ix e)
unsafeDefaultLinearShrink MArray (PrimState m) r ix e
marr Sz ix
sz = do
  MArray (PrimState m) r ix e
marr' <- Sz ix -> m (MArray (PrimState m) r ix e)
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
Sz ix -> m (MArray (PrimState m) r ix e)
unsafeNew Sz ix
sz
  MArray (PrimState m) r ix e
-> Int -> MArray (PrimState m) r ix e -> Int -> Sz1 -> m ()
forall r ix e ix' (m :: * -> *).
(Mutable r ix e, Mutable r ix' e, PrimMonad m) =>
MArray (PrimState m) r ix' e
-> Int -> MArray (PrimState m) r ix e -> Int -> Sz1 -> m ()
unsafeLinearCopy MArray (PrimState m) r ix e
marr Int
0 MArray (PrimState m) r ix e
marr' Int
0 (Sz1 -> m ()) -> Sz1 -> m ()
forall a b. (a -> b) -> a -> b
$ Int -> Sz1
forall ix. ix -> Sz ix
SafeSz (Sz ix -> Int
forall ix. Index ix => Sz ix -> Int
totalElem Sz ix
sz)
  MArray (PrimState m) r ix e -> m (MArray (PrimState m) r ix e)
forall (f :: * -> *) a. Applicative f => a -> f a
pure MArray (PrimState m) r ix e
marr'
{-# INLINE unsafeDefaultLinearShrink #-}


-- | Read an array element
--
-- @since 0.1.0
unsafeRead :: (Mutable r ix e, PrimMonad m) =>
               MArray (PrimState m) r ix e -> ix -> m e
unsafeRead :: MArray (PrimState m) r ix e -> ix -> m e
unsafeRead MArray (PrimState m) r ix e
marr = MArray (PrimState m) r ix e -> Int -> m e
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
MArray (PrimState m) r ix e -> Int -> m e
unsafeLinearRead MArray (PrimState m) r ix e
marr (Int -> m e) -> (ix -> Int) -> ix -> m e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sz ix -> ix -> Int
forall ix. Index ix => Sz ix -> ix -> Int
toLinearIndex (MArray (PrimState m) r ix e -> Sz ix
forall r ix e s. Mutable r ix e => MArray s r ix e -> Sz ix
msize MArray (PrimState m) r ix e
marr)
{-# INLINE unsafeRead #-}

-- | Write an element into array
--
-- @since 0.1.0
unsafeWrite :: (Mutable r ix e, PrimMonad m) =>
               MArray (PrimState m) r ix e -> ix -> e -> m ()
unsafeWrite :: MArray (PrimState m) r ix e -> ix -> e -> m ()
unsafeWrite MArray (PrimState m) r ix e
marr = MArray (PrimState m) r ix e -> Int -> e -> m ()
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
MArray (PrimState m) r ix e -> Int -> e -> m ()
unsafeLinearWrite MArray (PrimState m) r ix e
marr (Int -> e -> m ()) -> (ix -> Int) -> ix -> e -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sz ix -> ix -> Int
forall ix. Index ix => Sz ix -> ix -> Int
toLinearIndex (MArray (PrimState m) r ix e -> Sz ix
forall r ix e s. Mutable r ix e => MArray s r ix e -> Sz ix
msize MArray (PrimState m) r ix e
marr)
{-# INLINE unsafeWrite #-}


-- | Modify an element in the array with a monadic action. Returns the previous value.
--
-- @since 0.4.0
unsafeLinearModify :: (Mutable r ix e, PrimMonad m) =>
                      MArray (PrimState m) r ix e -> (e -> m e) -> Int -> m e
unsafeLinearModify :: MArray (PrimState m) r ix e -> (e -> m e) -> Int -> m e
unsafeLinearModify !MArray (PrimState m) r ix e
marr e -> m e
f !Int
i = do
  e
v <- MArray (PrimState m) r ix e -> Int -> m e
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
MArray (PrimState m) r ix e -> Int -> m e
unsafeLinearRead MArray (PrimState m) r ix e
marr Int
i
  e
v' <- e -> m e
f e
v
  MArray (PrimState m) r ix e -> Int -> e -> m ()
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
MArray (PrimState m) r ix e -> Int -> e -> m ()
unsafeLinearWrite MArray (PrimState m) r ix e
marr Int
i e
v'
  e -> m e
forall (f :: * -> *) a. Applicative f => a -> f a
pure e
v
{-# INLINE unsafeLinearModify #-}

-- | Modify an element in the array with a monadic action. Returns the previous value.
--
-- @since 0.4.0
unsafeModify :: (Mutable r ix e, PrimMonad m) =>
                MArray (PrimState m) r ix e -> (e -> m e) -> ix -> m e
unsafeModify :: MArray (PrimState m) r ix e -> (e -> m e) -> ix -> m e
unsafeModify MArray (PrimState m) r ix e
marr e -> m e
f ix
ix = MArray (PrimState m) r ix e -> (e -> m e) -> Int -> m e
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
MArray (PrimState m) r ix e -> (e -> m e) -> Int -> m e
unsafeLinearModify MArray (PrimState m) r ix e
marr e -> m e
f (Sz ix -> ix -> Int
forall ix. Index ix => Sz ix -> ix -> Int
toLinearIndex (MArray (PrimState m) r ix e -> Sz ix
forall r ix e s. Mutable r ix e => MArray s r ix e -> Sz ix
msize MArray (PrimState m) r ix e
marr) ix
ix)
{-# INLINE unsafeModify #-}

-- | Swap two elements in a mutable array under the supplied indices. Returns the previous
-- values.
--
-- @since 0.4.0
unsafeSwap :: (Mutable r ix e, PrimMonad m) =>
                    MArray (PrimState m) r ix e -> ix -> ix -> m (e, e)
unsafeSwap :: MArray (PrimState m) r ix e -> ix -> ix -> m (e, e)
unsafeSwap !MArray (PrimState m) r ix e
marr !ix
ix1 !ix
ix2 = MArray (PrimState m) r ix e -> Int -> Int -> m (e, e)
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
MArray (PrimState m) r ix e -> Int -> Int -> m (e, e)
unsafeLinearSwap MArray (PrimState m) r ix e
marr (Sz ix -> ix -> Int
forall ix. Index ix => Sz ix -> ix -> Int
toLinearIndex Sz ix
sz ix
ix1) (Sz ix -> ix -> Int
forall ix. Index ix => Sz ix -> ix -> Int
toLinearIndex Sz ix
sz ix
ix2)
  where sz :: Sz ix
sz = MArray (PrimState m) r ix e -> Sz ix
forall r ix e s. Mutable r ix e => MArray s r ix e -> Sz ix
msize MArray (PrimState m) r ix e
marr
{-# INLINE unsafeSwap #-}


-- | Swap two elements in a mutable array under the supplied linear indices. Returns the
-- previous values.
--
-- @since 0.4.0
unsafeLinearSwap :: (Mutable r ix e, PrimMonad m) =>
                    MArray (PrimState m) r ix e -> Int -> Int -> m (e, e)
unsafeLinearSwap :: MArray (PrimState m) r ix e -> Int -> Int -> m (e, e)
unsafeLinearSwap !MArray (PrimState m) r ix e
marr !Int
i1 !Int
i2 = do
  e
val1 <- MArray (PrimState m) r ix e -> Int -> m e
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
MArray (PrimState m) r ix e -> Int -> m e
unsafeLinearRead MArray (PrimState m) r ix e
marr Int
i1
  e
val2 <- MArray (PrimState m) r ix e -> Int -> m e
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
MArray (PrimState m) r ix e -> Int -> m e
unsafeLinearRead MArray (PrimState m) r ix e
marr Int
i2
  MArray (PrimState m) r ix e -> Int -> e -> m ()
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
MArray (PrimState m) r ix e -> Int -> e -> m ()
unsafeLinearWrite MArray (PrimState m) r ix e
marr Int
i1 e
val2
  MArray (PrimState m) r ix e -> Int -> e -> m ()
forall r ix e (m :: * -> *).
(Mutable r ix e, PrimMonad m) =>
MArray (PrimState m) r ix e -> Int -> e -> m ()
unsafeLinearWrite MArray (PrimState m) r ix e
marr Int
i2 e
val1
  (e, e) -> m (e, e)
forall (m :: * -> *) a. Monad m => a -> m a
return (e
val1, e
val2)
{-# INLINE unsafeLinearSwap #-}


class Nested r ix e where
  fromNested :: NestedStruct r ix e -> Array r ix e

  toNested :: Array r ix e -> NestedStruct r ix e

class Construct r ix e => Ragged r ix e where

  emptyR :: Comp -> Array r ix e

  isNull :: Array r ix e -> Bool

  consR :: Elt r ix e -> Array r ix e -> Array r ix e

  unconsR :: Array r ix e -> Maybe (Elt r ix e, Array r ix e)

  generateRaggedM :: Monad m => Comp -> Sz ix -> (ix -> m e) -> m (Array r ix e)

  edgeSize :: Array r ix e -> Sz ix

  flattenRagged :: Array r ix e -> Array r Ix1 e

  loadRagged ::
    Monad m => (m () -> m ()) -> (Int -> e -> m a) -> Int -> Int -> Sz ix -> Array r ix e -> m ()

  -- TODO: test property:
  -- (read $ raggedFormat show "\n" (ls :: Array L (IxN n) Int)) == ls
  raggedFormat :: (e -> String) -> String -> Array r ix e -> String



-- | Create an Array with no elements. By itself it is not particularly useful, but it serves as a
-- nice base for constructing larger arrays.
--
-- ==== __Examples__
--
-- >>> import Data.Massiv.Array as A
-- >>> :set -XTypeApplications
-- >>> xs = empty @DL @Ix1 @Double
-- >>> snoc (cons 4 (cons 5 xs)) 22
-- Array DL Seq (Sz1 3)
--   [ 4.0, 5.0, 22.0 ]
--
-- @since 0.3.0
empty ::
     forall r ix e. Construct r ix e
  => Array r ix e
empty :: Array r ix e
empty = Comp -> Sz ix -> (ix -> e) -> Array r ix e
forall r ix e.
Construct r ix e =>
Comp -> Sz ix -> (ix -> e) -> Array r ix e
makeArray Comp
Seq Sz ix
forall ix. Index ix => Sz ix
zeroSz (e -> ix -> e
forall a b. a -> b -> a
const (Uninitialized -> e
forall e a. Exception e => e -> a
throwImpossible Uninitialized
Uninitialized))
{-# INLINE empty #-}

-- | Create an Array with a single element.
--
-- ==== __Examples__
--
-- >>> import Data.Massiv.Array as A
-- >>> singleton 7 :: Array D Ix4 Double
-- Array D Seq (Sz (1 :> 1 :> 1 :. 1))
--   [ [ [ [ 7.0 ]
--       ]
--     ]
--   ]
--
-- Instead of specifying type signature we could use @TypeApplications@
--
-- >>> :set -XTypeApplications
-- >>> singleton @U @Ix4 @Double 7
-- Array U Seq (Sz (1 :> 1 :> 1 :. 1))
--   [ [ [ [ 7.0 ]
--       ]
--     ]
--   ]
--
-- @since 0.1.0
singleton ::
     forall r ix e. Construct r ix e
  => e -- ^ The only element
  -> Array r ix e
singleton :: e -> Array r ix e
singleton = Comp -> Sz ix -> (ix -> e) -> Array r ix e
forall r ix e.
Construct r ix e =>
Comp -> Sz ix -> (ix -> e) -> Array r ix e
makeArray Comp
Seq Sz ix
forall ix. Index ix => Sz ix
oneSz ((ix -> e) -> Array r ix e) -> (e -> ix -> e) -> e -> Array r ix e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> ix -> e
forall a b. a -> b -> a
const
{-# INLINE singleton #-}


infixl 4 !, !?, ??

-- | /O(1)/ - Infix version of `index'`.
--
-- ==== __Examples__
--
-- >>> import Data.Massiv.Array as A
-- >>> a = computeAs U $ iterateN (Sz (2 :. 3)) succ (0 :: Int)
-- >>> a
-- Array U Seq (Sz (2 :. 3))
--   [ [ 1, 2, 3 ]
--   , [ 4, 5, 6 ]
--   ]
-- >>> a ! 0 :. 2
-- 3
-- >>> a ! 0 :. 3
-- *** Exception: IndexOutOfBoundsException: (0 :. 3) is not safe for (Sz (2 :. 3))
--
-- @since 0.1.0
(!) :: Manifest r ix e => Array r ix e -> ix -> e
(!) = Array r ix e -> ix -> e
forall r ix e. Manifest r ix e => Array r ix e -> ix -> e
index'
{-# INLINE (!) #-}


-- | /O(1)/ - Infix version of `indexM`.
--
-- /__Exceptions__/: `IndexOutOfBoundsException`
--
-- ==== __Examples__
--
-- >>> import Data.Massiv.Array as A
-- >>> :set -XTypeApplications
-- >>> a <- fromListsM @U @Ix2 @Int Seq [[1,2,3],[4,5,6]]
-- >>> a
-- Array U Seq (Sz (2 :. 3))
--   [ [ 1, 2, 3 ]
--   , [ 4, 5, 6 ]
--   ]
-- >>> a !? 0 :. 2
-- 3
-- >>> a !? 0 :. 3
-- *** Exception: IndexOutOfBoundsException: (0 :. 3) is not safe for (Sz (2 :. 3))
-- >>> a !? 0 :. 3 :: Maybe Int
-- Nothing
--
-- @since 0.1.0
(!?) :: (Manifest r ix e, MonadThrow m) => Array r ix e -> ix -> m e
!? :: Array r ix e -> ix -> m e
(!?) = Array r ix e -> ix -> m e
forall r ix e (m :: * -> *).
(Manifest r ix e, MonadThrow m) =>
Array r ix e -> ix -> m e
indexM
{-# INLINE (!?) #-}


-- | /O(1)/ - Lookup an element in the array, where array itself is wrapped with
-- `MonadThrow`. This operator is useful when used together with slicing or other
-- functions that can fail.
--
-- /__Exceptions__/: `IndexOutOfBoundsException`
--
-- ==== __Examples__
--
-- >>> import Data.Massiv.Array as A
-- >>> :set -XTypeApplications
-- >>> ma = fromListsM @U @Ix3 @Int @Maybe Seq [[[1,2,3]],[[4,5,6]]]
-- >>> ma
-- Just (Array U Seq (Sz (2 :> 1 :. 3))
--   [ [ [ 1, 2, 3 ]
--     ]
--   , [ [ 4, 5, 6 ]
--     ]
--   ]
-- )
-- >>> ma ??> 1
-- Just (Array M Seq (Sz (1 :. 3))
--   [ [ 4, 5, 6 ]
--   ]
-- )
-- >>> ma ??> 1 ?? 0 :. 2
-- Just 6
-- >>> ma ?? 1 :> 0 :. 2
-- Just 6
--
-- @since 0.1.0
(??) :: (Manifest r ix e, MonadThrow m) => m (Array r ix e) -> ix -> m e
?? :: m (Array r ix e) -> ix -> m e
(??) m (Array r ix e)
marr ix
ix = m (Array r ix e)
marr m (Array r ix e) -> (Array r ix e -> m e) -> m e
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Array r ix e -> ix -> m e
forall r ix e (m :: * -> *).
(Manifest r ix e, MonadThrow m) =>
Array r ix e -> ix -> m e
!? ix
ix)
{-# INLINE (??) #-}

-- | /O(1)/ - Lookup an element in the array. Returns `Nothing`, when index is out of bounds and
-- returns the element at the supplied index otherwise. Use `indexM` instead, since it is more
-- general and it can just as well be used with `Maybe`.
--
-- @since 0.1.0
index :: Manifest r ix e => Array r ix e -> ix -> Maybe e
index :: Array r ix e -> ix -> Maybe e
index = Array r ix e -> ix -> Maybe e
forall r ix e (m :: * -> *).
(Manifest r ix e, MonadThrow m) =>
Array r ix e -> ix -> m e
indexM
{-# INLINE index #-}

-- | /O(1)/ - Lookup an element in the array.
--
-- /__Exceptions__/: `IndexOutOfBoundsException`
--
-- @since 0.3.0
indexM :: (Manifest r ix e, MonadThrow m) => Array r ix e -> ix -> m e
indexM :: Array r ix e -> ix -> m e
indexM = Array r ix e -> ix -> m e
forall r ix e (m :: * -> *).
(Source r ix e, MonadThrow m) =>
Array r ix e -> ix -> m e
evaluateM
{-# INLINE indexM #-}

-- | /O(1)/ - Lookup an element in the array, while using default element when index is out of
-- bounds.
--
-- ==== __Examples__
--
-- >>> import Data.Massiv.Array
-- >>> :set -XOverloadedLists
-- >>> xs = [0..100] :: Array P Ix1 Int
-- >>> defaultIndex 999 xs 100
-- 100
-- >>> defaultIndex 999 xs 101
-- 999
--
-- @since 0.1.0
defaultIndex :: Manifest r ix e => e -> Array r ix e -> ix -> e
defaultIndex :: e -> Array r ix e -> ix -> e
defaultIndex e
defVal = Border e -> Array r ix e -> ix -> e
forall r ix e.
Manifest r ix e =>
Border e -> Array r ix e -> ix -> e
borderIndex (e -> Border e
forall e. e -> Border e
Fill e
defVal)
{-# INLINE defaultIndex #-}

-- | /O(1)/ - Lookup an element in the array. Use a border resolution technique
-- when index is out of bounds.
--
-- ==== __Examples__
--
-- >>> import Data.Massiv.Array as A
-- >>> :set -XOverloadedLists
-- >>> xs = [0..100] :: Array U Ix1 Int
-- >>> borderIndex Wrap xs <$> range Seq 99 104
-- Array D Seq (Sz1 5)
--   [ 99, 100, 0, 1, 2 ]
--
-- @since 0.1.0
borderIndex :: Manifest r ix e => Border e -> Array r ix e -> ix -> e
borderIndex :: Border e -> Array r ix e -> ix -> e
borderIndex Border e
border Array r ix e
arr = Border e -> Sz ix -> (ix -> e) -> ix -> e
forall ix e. Index ix => Border e -> Sz ix -> (ix -> e) -> ix -> e
handleBorderIndex Border e
border (Array r ix e -> Sz ix
forall r ix e. Load r ix e => Array r ix e -> Sz ix
size Array r ix e
arr) (Array r ix e -> ix -> e
forall r ix e. Source r ix e => Array r ix e -> ix -> e
unsafeIndex Array r ix e
arr)
{-# INLINE borderIndex #-}

-- | /O(1)/ - Lookup an element in the array. This is a partial function and it can throw
-- `IndexOutOfBoundsException` inside pure code. It is safer to use `index` instead.
--
-- ==== __Examples__
--
-- >>> import Data.Massiv.Array
-- >>> :set -XOverloadedLists
-- >>> xs = [0..100] :: Array U Ix1 Int
-- >>> index' xs 50
-- 50
-- >>> index' xs 150
-- *** Exception: IndexOutOfBoundsException: 150 is not safe for (Sz1 101)
--
-- @since 0.1.0
index' :: Manifest r ix e => Array r ix e -> ix -> e
index' :: Array r ix e -> ix -> e
index' = Array r ix e -> ix -> e
forall r ix e. Source r ix e => Array r ix e -> ix -> e
evaluate'
{-# INLINE index' #-}

-- | This is just like `indexM` function, but it allows getting values from
-- delayed arrays as well as `Manifest`. As the name suggests, indexing into a
-- delayed array at the same index multiple times will cause evaluation of the
-- value each time and can destroy the performace if used without care.
--
-- ==== __Examples__
--
-- >>> import Control.Exception
-- >>> import Data.Massiv.Array
-- >>> evaluateM (range Seq (Ix2 10 20) (100 :. 210)) 50 :: Either SomeException Ix2
-- Right (60 :. 70)
-- >>> evaluateM (range Seq (Ix2 10 20) (100 :. 210)) 150 :: Either SomeException Ix2
-- Left (IndexOutOfBoundsException: (150 :. 150) is not safe for (Sz (90 :. 190)))
--
-- @since 0.3.0
evaluateM :: (Source r ix e, MonadThrow m) => Array r ix e -> ix -> m e
evaluateM :: Array r ix e -> ix -> m e
evaluateM Array r ix e
arr ix
ix =
  Border (m e) -> Sz ix -> (ix -> m e) -> ix -> m e
forall ix e. Index ix => Border e -> Sz ix -> (ix -> e) -> ix -> e
handleBorderIndex
    (m e -> Border (m e)
forall e. e -> Border e
Fill (IndexException -> m e
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (Sz ix -> ix -> IndexException
forall ix. Index ix => Sz ix -> ix -> IndexException
IndexOutOfBoundsException (Array r ix e -> Sz ix
forall r ix e. Load r ix e => Array r ix e -> Sz ix
size Array r ix e
arr) ix
ix)))
    (Array r ix e -> Sz ix
forall r ix e. Load r ix e => Array r ix e -> Sz ix
size Array r ix e
arr)
    (e -> m e
forall (f :: * -> *) a. Applicative f => a -> f a
pure (e -> m e) -> (ix -> e) -> ix -> m e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Array r ix e -> ix -> e
forall r ix e. Source r ix e => Array r ix e -> ix -> e
unsafeIndex Array r ix e
arr)
    ix
ix
{-# INLINE evaluateM #-}

-- | Similar to `evaluateM`, but will throw an exception in pure code.
--
-- ==== __Examples__
--
-- >>> import Data.Massiv.Array
-- >>> evaluate' (range Seq (Ix2 10 20) (100 :. 210)) 50
-- 60 :. 70
-- >>> evaluate' (range Seq (Ix2 10 20) (100 :. 210)) 150
-- *** Exception: IndexOutOfBoundsException: (150 :. 150) is not safe for (Sz (90 :. 190))
--
-- @since 0.3.0
evaluate' :: Source r ix e => Array r ix e -> ix -> e
evaluate' :: Array r ix e -> ix -> e
evaluate' Array r ix e
arr ix
ix =
  Border e -> Sz ix -> (ix -> e) -> ix -> e
forall ix e. Index ix => Border e -> Sz ix -> (ix -> e) -> ix -> e
handleBorderIndex
    (e -> Border e
forall e. e -> Border e
Fill (IndexException -> e
forall a e. Exception e => e -> a
throw (Sz ix -> ix -> IndexException
forall ix. Index ix => Sz ix -> ix -> IndexException
IndexOutOfBoundsException (Array r ix e -> Sz ix
forall r ix e. Load r ix e => Array r ix e -> Sz ix
size Array r ix e
arr) ix
ix)))
    (Array r ix e -> Sz ix
forall r ix e. Load r ix e => Array r ix e -> Sz ix
size Array r ix e
arr)
    (Array r ix e -> ix -> e
forall r ix e. Source r ix e => Array r ix e -> ix -> e
unsafeIndex Array r ix e
arr)
    ix
ix
{-# INLINE evaluate' #-}


-- | Map a monadic index aware function over an array sequentially, while discarding the result.
--
-- ==== __Examples__
--
-- >>> import Data.Massiv.Array
-- >>> imapM_ (curry print) $ range Seq (Ix1 10) 15
-- (0,10)
-- (1,11)
-- (2,12)
-- (3,13)
-- (4,14)
--
-- @since 0.1.0
imapM_ :: (Source r ix a, Monad m) => (ix -> a -> m b) -> Array r ix a -> m ()
imapM_ :: (ix -> a -> m b) -> Array r ix a -> m ()
imapM_ ix -> a -> m b
f !Array r ix a
arr =
  ix -> ix -> ix -> (Int -> Int -> Bool) -> (ix -> m b) -> m ()
forall ix (m :: * -> *) a.
(Index ix, Monad m) =>
ix -> ix -> ix -> (Int -> Int -> Bool) -> (ix -> m a) -> m ()
iterM_ ix
forall ix. Index ix => ix
zeroIndex (Sz ix -> ix
forall ix. Sz ix -> ix
unSz (Array r ix a -> Sz ix
forall r ix e. Load r ix e => Array r ix e -> Sz ix
size Array r ix a
arr)) (Int -> ix
forall ix. Index ix => Int -> ix
pureIndex Int
1) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
(<) ((ix -> m b) -> m ()) -> (ix -> m b) -> m ()
forall a b. (a -> b) -> a -> b
$ \ !ix
ix -> ix -> a -> m b
f ix
ix (Array r ix a -> ix -> a
forall r ix e. Source r ix e => Array r ix e -> ix -> e
unsafeIndex Array r ix a
arr ix
ix)
{-# INLINE imapM_ #-}


-- | /O(1)/ - Get the number of elements in the array.
--
-- /Note/ - It is always a constant time operation except for some arrays with
-- `Data.Massiv.Array.DS` representation. See `Data.Massiv.Vector.slength` for more info.
--
-- ==== __Examples__
--
-- >>> import Data.Massiv.Array
-- >>> elemsCount $ range Seq (Ix1 10) 15
-- 5
--
-- @since 0.1.0
elemsCount :: Load r ix e => Array r ix e -> Int
elemsCount :: Array r ix e -> Int
elemsCount = Sz ix -> Int
forall ix. Index ix => Sz ix -> Int
totalElem (Sz ix -> Int) -> (Array r ix e -> Sz ix) -> Array r ix e -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Array r ix e -> Sz ix
forall r ix e. Load r ix e => Array r ix e -> Sz ix
size
{-# INLINE elemsCount #-}


-- | Get the number of elements in the array
--
-- @since 0.5.8
linearSize :: Load r ix e => Array r ix e -> Sz1
linearSize :: Array r ix e -> Sz1
linearSize = Sz ix -> Sz1
forall ix. Index ix => Sz ix -> Sz1
toLinearSz (Sz ix -> Sz1) -> (Array r ix e -> Sz ix) -> Array r ix e -> Sz1
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Array r ix e -> Sz ix
forall r ix e. Load r ix e => Array r ix e -> Sz ix
size
{-# INLINE linearSize #-}


-- | /O(1)/ - Check if array has elements.
--
-- ==== __Examples__
--
-- >>> import Data.Massiv.Array
-- >>> isNotEmpty (singleton 1 :: Array D Ix2 Int)
-- True
-- >>> isNotEmpty (empty :: Array D Ix2 Int)
-- False
--
-- @since 0.5.1
isNotEmpty :: Load r ix e => Array r ix e -> Bool
isNotEmpty :: Array r ix e -> Bool
isNotEmpty = Bool -> Bool
not (Bool -> Bool) -> (Array r ix e -> Bool) -> Array r ix e -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Array r ix e -> Bool
forall r ix e. Load r ix e => Array r ix e -> Bool
isEmpty
{-# INLINE isNotEmpty #-}