module Data.PrimitiveArray.Class where
import Control.Applicative (Applicative, pure, (<$>), (<*>))
import Control.Exception (assert)
import Control.Monad.Except
import Control.Monad (forM_)
import Control.Monad.Primitive (PrimMonad, liftPrim)
import Control.Monad.ST (runST)
import Data.Proxy
import Data.Vector.Fusion.Util
import Debug.Trace
import GHC.Generics (Generic)
import Prelude as P
import qualified Data.Vector.Fusion.Stream.Monadic as SM
import GHC.Stack
import Data.Kind (Constraint)
import Data.PrimitiveArray.Index.Class
data family MutArr (m :: * -> *) (arr :: *) :: *
type family FillStruc arr :: *
class (Index sh) => PrimArrayOps arr sh elm where
upperBound :: arr sh elm -> LimitType sh
unsafeIndex :: arr sh elm -> sh -> elm
safeIndex :: arr sh elm -> sh -> Maybe elm
transformShape :: Index sh' => (LimitType sh -> LimitType sh') -> arr sh elm -> arr sh' elm
upperBoundM :: MutArr m (arr sh elm) -> LimitType sh
fromListM :: PrimMonad m => LimitType sh -> [elm] -> m (MutArr m (arr sh elm))
newM :: PrimMonad m => LimitType sh -> m (MutArr m (arr sh elm))
newSM :: (Monad m, PrimMonad m) => LimitType sh -> FillStruc (arr sh elm) -> m (MutArr m (arr sh elm))
newWithM :: PrimMonad m => LimitType sh -> elm -> m (MutArr m (arr sh elm))
newWithSM :: (Monad m, PrimMonad m) => LimitType sh -> FillStruc (arr sh elm) -> elm -> m (MutArr m (arr sh elm))
readM :: PrimMonad m => MutArr m (arr sh elm) -> sh -> m elm
safeReadM :: (Monad m, PrimMonad m) => MutArr m (arr sh elm) -> sh -> m (Maybe elm)
writeM :: PrimMonad m => MutArr m (arr sh elm) -> sh -> elm -> m ()
safeWriteM :: (Monad m, PrimMonad m) => MutArr m (arr sh elm) -> sh -> elm -> m ()
unsafeFreezeM :: PrimMonad m => MutArr m (arr sh elm) -> m (arr sh elm)
unsafeThawM :: PrimMonad m => arr sh elm -> m (MutArr m (arr sh elm))
class PrimArrayMap arr sh e e' where
mapArray :: (e -> e') -> arr sh e -> arr sh e'
data PAErrors
= PAEUpperBound
deriving stock (PAErrors -> PAErrors -> Bool
(PAErrors -> PAErrors -> Bool)
-> (PAErrors -> PAErrors -> Bool) -> Eq PAErrors
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PAErrors -> PAErrors -> Bool
$c/= :: PAErrors -> PAErrors -> Bool
== :: PAErrors -> PAErrors -> Bool
$c== :: PAErrors -> PAErrors -> Bool
Eq,(forall x. PAErrors -> Rep PAErrors x)
-> (forall x. Rep PAErrors x -> PAErrors) -> Generic PAErrors
forall x. Rep PAErrors x -> PAErrors
forall x. PAErrors -> Rep PAErrors x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep PAErrors x -> PAErrors
$cfrom :: forall x. PAErrors -> Rep PAErrors x
Generic)
instance Show PAErrors where
show :: PAErrors -> String
show (PAErrors
PAEUpperBound) = String
"Upper bound is too large for @Int@ size!"
(!) :: (PrimArrayOps arr sh elm) => arr sh elm -> sh -> elm
{-# Inline [1] (!) #-}
{-# Rules "unsafeIndex" [2] (!) = unsafeIndex #-}
(!) = \arr sh elm
arr sh
idx -> case arr sh elm -> sh -> Maybe elm
forall (arr :: * -> * -> *) sh elm.
PrimArrayOps arr sh elm =>
arr sh elm -> sh -> Maybe elm
safeIndex arr sh elm
arr sh
idx of
Maybe elm
Nothing -> String -> elm
forall a. HasCallStack => String -> a
error (String -> elm) -> String -> elm
forall a b. (a -> b) -> a -> b
$ ([String], [String]) -> String
forall a. Show a => a -> String
show (LimitType sh -> [String]
forall i. Index i => LimitType i -> [String]
showBound (arr sh elm -> LimitType sh
forall (arr :: * -> * -> *) sh elm.
PrimArrayOps arr sh elm =>
arr sh elm -> LimitType sh
upperBound arr sh elm
arr), sh -> [String]
forall i. Index i => i -> [String]
showIndex sh
idx)
Just elm
v -> elm
v
(!?) :: PrimArrayOps arr sh elm => arr sh elm -> sh -> Maybe elm
{-# Inline (!?) #-}
!? :: arr sh elm -> sh -> Maybe elm
(!?) = arr sh elm -> sh -> Maybe elm
forall (arr :: * -> * -> *) sh elm.
PrimArrayOps arr sh elm =>
arr sh elm -> sh -> Maybe elm
safeIndex
inBoundsM :: (Monad m, PrimArrayOps arr sh elm) => MutArr m (arr sh elm) -> sh -> Bool
inBoundsM :: MutArr m (arr sh elm) -> sh -> Bool
inBoundsM MutArr m (arr sh elm)
marr sh
idx = LimitType sh -> sh -> Bool
forall i. Index i => LimitType i -> i -> Bool
inBounds (MutArr m (arr sh elm) -> LimitType sh
forall (arr :: * -> * -> *) sh elm (m :: * -> *).
PrimArrayOps arr sh elm =>
MutArr m (arr sh elm) -> LimitType sh
upperBoundM MutArr m (arr sh elm)
marr) sh
idx
{-# INLINE inBoundsM #-}
fromAssocsM
:: (PrimMonad m, PrimArrayOps arr sh elm)
=> LimitType sh -> elm -> [(sh,elm)] -> m (MutArr m (arr sh elm))
fromAssocsM :: LimitType sh -> elm -> [(sh, elm)] -> m (MutArr m (arr sh elm))
fromAssocsM LimitType sh
ub elm
def [(sh, elm)]
xs = do
MutArr m (arr sh elm)
ma <- LimitType sh -> elm -> m (MutArr m (arr sh elm))
forall (arr :: * -> * -> *) sh elm (m :: * -> *).
(PrimArrayOps arr sh elm, PrimMonad m) =>
LimitType sh -> elm -> m (MutArr m (arr sh elm))
newWithM LimitType sh
ub elm
def
[(sh, elm)] -> ((sh, elm) -> m ()) -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [(sh, elm)]
xs (((sh, elm) -> m ()) -> m ()) -> ((sh, elm) -> m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ \(sh
k,elm
v) -> MutArr m (arr sh elm) -> sh -> elm -> m ()
forall (arr :: * -> * -> *) sh elm (m :: * -> *).
(PrimArrayOps arr sh elm, PrimMonad m) =>
MutArr m (arr sh elm) -> sh -> elm -> m ()
writeM MutArr m (arr sh elm)
ma sh
k elm
v
MutArr m (arr sh elm) -> m (MutArr m (arr sh elm))
forall (m :: * -> *) a. Monad m => a -> m a
return MutArr m (arr sh elm)
ma
{-# INLINE fromAssocsM #-}
newWithPA
:: (PrimMonad m, PrimArrayOps arr sh elm)
=> LimitType sh
-> elm
-> m (arr sh elm)
newWithPA :: LimitType sh -> elm -> m (arr sh elm)
newWithPA LimitType sh
ub elm
def = do
MutArr m (arr sh elm)
ma ← LimitType sh -> elm -> m (MutArr m (arr sh elm))
forall (arr :: * -> * -> *) sh elm (m :: * -> *).
(PrimArrayOps arr sh elm, PrimMonad m) =>
LimitType sh -> elm -> m (MutArr m (arr sh elm))
newWithM LimitType sh
ub elm
def
MutArr m (arr sh elm) -> m (arr sh elm)
forall (arr :: * -> * -> *) sh elm (m :: * -> *).
(PrimArrayOps arr sh elm, PrimMonad m) =>
MutArr m (arr sh elm) -> m (arr sh elm)
unsafeFreezeM MutArr m (arr sh elm)
ma
{-# Inlinable newWithPA #-}
newWithSPA
∷ (PrimMonad m, PrimArrayOps arr sh elm)
⇒ LimitType sh
-> FillStruc (arr sh elm)
→ elm
→ m (arr sh elm)
{-# Inlinable newWithSPA #-}
newWithSPA :: LimitType sh -> FillStruc (arr sh elm) -> elm -> m (arr sh elm)
newWithSPA LimitType sh
ub FillStruc (arr sh elm)
xs elm
def = do
MutArr m (arr sh elm)
ma ← LimitType sh
-> FillStruc (arr sh elm) -> elm -> m (MutArr m (arr sh elm))
forall (arr :: * -> * -> *) sh elm (m :: * -> *).
(PrimArrayOps arr sh elm, Monad m, PrimMonad m) =>
LimitType sh
-> FillStruc (arr sh elm) -> elm -> m (MutArr m (arr sh elm))
newWithSM LimitType sh
ub FillStruc (arr sh elm)
xs elm
def
MutArr m (arr sh elm) -> m (arr sh elm)
forall (arr :: * -> * -> *) sh elm (m :: * -> *).
(PrimArrayOps arr sh elm, PrimMonad m) =>
MutArr m (arr sh elm) -> m (arr sh elm)
unsafeFreezeM MutArr m (arr sh elm)
ma
safeNewWithPA
:: forall m arr sh elm
. (PrimMonad m, MonadError PAErrors m, PrimArrayOps arr sh elm)
=> LimitType sh
-> elm
-> m (arr sh elm)
safeNewWithPA :: LimitType sh -> elm -> m (arr sh elm)
safeNewWithPA LimitType sh
ub elm
def = do
case Except SizeError CellSize -> Either SizeError CellSize
forall e a. Except e a -> Either e a
runExcept (Except SizeError CellSize -> Either SizeError CellSize)
-> Except SizeError CellSize -> Either SizeError CellSize
forall a b. (a -> b) -> a -> b
$ Word -> [[Integer]] -> Except SizeError CellSize
forall (m :: * -> *).
Monad m =>
Word -> [[Integer]] -> ExceptT SizeError m CellSize
sizeIsValid Word
forall a. Bounded a => a
maxBound [LimitType sh -> [Integer]
forall i. Index i => LimitType i -> [Integer]
totalSize LimitType sh
ub] of
Left (SizeError String
_) -> PAErrors -> m (arr sh elm)
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError PAErrors
PAEUpperBound
Right (CellSize Word
_) -> LimitType sh -> elm -> m (arr sh elm)
forall (m :: * -> *) (arr :: * -> * -> *) sh elm.
(PrimMonad m, PrimArrayOps arr sh elm) =>
LimitType sh -> elm -> m (arr sh elm)
newWithPA LimitType sh
ub elm
def
{-# Inlinable safeNewWithPA #-}
assocs :: forall arr sh elm . (IndexStream sh, PrimArrayOps arr sh elm) => arr sh elm -> [(sh,elm)]
assocs :: arr sh elm -> [(sh, elm)]
assocs arr sh elm
arr = Id [(sh, elm)] -> [(sh, elm)]
forall a. Id a -> a
unId (Id [(sh, elm)] -> [(sh, elm)])
-> (Stream Id (sh, elm) -> Id [(sh, elm)])
-> Stream Id (sh, elm)
-> [(sh, elm)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stream Id (sh, elm) -> Id [(sh, elm)]
forall (m :: * -> *) a. Monad m => Stream m a -> m [a]
SM.toList (Stream Id (sh, elm) -> [(sh, elm)])
-> Stream Id (sh, elm) -> [(sh, elm)]
forall a b. (a -> b) -> a -> b
$ arr sh elm -> Stream Id (sh, elm)
forall (m :: * -> *) (arr :: * -> * -> *) sh elm.
(Monad m, IndexStream sh, PrimArrayOps arr sh elm) =>
arr sh elm -> Stream m (sh, elm)
assocsS arr sh elm
arr
{-# INLINE assocs #-}
assocsS :: forall m arr sh elm . (Monad m, IndexStream sh, PrimArrayOps arr sh elm) => arr sh elm -> SM.Stream m (sh,elm)
assocsS :: arr sh elm -> Stream m (sh, elm)
assocsS arr sh elm
arr = (sh -> (sh, elm)) -> Stream m sh -> Stream m (sh, elm)
forall (m :: * -> *) a b.
Monad m =>
(a -> b) -> Stream m a -> Stream m b
SM.map (\sh
k -> (sh
k,arr sh elm -> sh -> elm
forall (arr :: * -> * -> *) sh elm.
PrimArrayOps arr sh elm =>
arr sh elm -> sh -> elm
unsafeIndex arr sh elm
arr sh
k)) (Stream m sh -> Stream m (sh, elm))
-> Stream m sh -> Stream m (sh, elm)
forall a b. (a -> b) -> a -> b
$ LimitType sh -> LimitType sh -> Stream m sh
forall i (m :: * -> *).
(IndexStream i, Monad m) =>
LimitType i -> LimitType i -> Stream m i
streamUp LimitType sh
forall i. Index i => LimitType i
zeroBound' (arr sh elm -> LimitType sh
forall (arr :: * -> * -> *) sh elm.
PrimArrayOps arr sh elm =>
arr sh elm -> LimitType sh
upperBound arr sh elm
arr)
{-# INLINE assocsS #-}
fromList :: (PrimArrayOps arr sh elm) => LimitType sh -> [elm] -> arr sh elm
fromList :: LimitType sh -> [elm] -> arr sh elm
fromList LimitType sh
ub [elm]
xs = (forall s. ST s (arr sh elm)) -> arr sh elm
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s (arr sh elm)) -> arr sh elm)
-> (forall s. ST s (arr sh elm)) -> arr sh elm
forall a b. (a -> b) -> a -> b
$ LimitType sh -> [elm] -> ST s (MutArr (ST s) (arr sh elm))
forall (arr :: * -> * -> *) sh elm (m :: * -> *).
(PrimArrayOps arr sh elm, PrimMonad m) =>
LimitType sh -> [elm] -> m (MutArr m (arr sh elm))
fromListM LimitType sh
ub [elm]
xs ST s (MutArr (ST s) (arr sh elm))
-> (MutArr (ST s) (arr sh elm) -> ST s (arr sh elm))
-> ST s (arr sh elm)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= MutArr (ST s) (arr sh elm) -> ST s (arr sh elm)
forall (arr :: * -> * -> *) sh elm (m :: * -> *).
(PrimArrayOps arr sh elm, PrimMonad m) =>
MutArr m (arr sh elm) -> m (arr sh elm)
unsafeFreezeM
{-# INLINE fromList #-}
fromAssocs :: (PrimArrayOps arr sh elm) => LimitType sh -> elm -> [(sh,elm)] -> arr sh elm
fromAssocs :: LimitType sh -> elm -> [(sh, elm)] -> arr sh elm
fromAssocs LimitType sh
ub elm
def [(sh, elm)]
xs = (forall s. ST s (arr sh elm)) -> arr sh elm
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s (arr sh elm)) -> arr sh elm)
-> (forall s. ST s (arr sh elm)) -> arr sh elm
forall a b. (a -> b) -> a -> b
$ LimitType sh
-> elm -> [(sh, elm)] -> ST s (MutArr (ST s) (arr sh elm))
forall (m :: * -> *) (arr :: * -> * -> *) sh elm.
(PrimMonad m, PrimArrayOps arr sh elm) =>
LimitType sh -> elm -> [(sh, elm)] -> m (MutArr m (arr sh elm))
fromAssocsM LimitType sh
ub elm
def [(sh, elm)]
xs ST s (MutArr (ST s) (arr sh elm))
-> (MutArr (ST s) (arr sh elm) -> ST s (arr sh elm))
-> ST s (arr sh elm)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= MutArr (ST s) (arr sh elm) -> ST s (arr sh elm)
forall (arr :: * -> * -> *) sh elm (m :: * -> *).
(PrimArrayOps arr sh elm, PrimMonad m) =>
MutArr m (arr sh elm) -> m (arr sh elm)
unsafeFreezeM
{-# INLINE fromAssocs #-}
toList :: forall arr sh elm . (IndexStream sh, PrimArrayOps arr sh elm) => arr sh elm -> [elm]
toList :: arr sh elm -> [elm]
toList arr sh elm
arr = let ub :: LimitType sh
ub = arr sh elm -> LimitType sh
forall (arr :: * -> * -> *) sh elm.
PrimArrayOps arr sh elm =>
arr sh elm -> LimitType sh
upperBound arr sh elm
arr in (sh -> elm) -> [sh] -> [elm]
forall a b. (a -> b) -> [a] -> [b]
P.map ((!) arr sh elm
arr) ([sh] -> [elm]) -> (Stream Id sh -> [sh]) -> Stream Id sh -> [elm]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Id [sh] -> [sh]
forall a. Id a -> a
unId (Id [sh] -> [sh])
-> (Stream Id sh -> Id [sh]) -> Stream Id sh -> [sh]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stream Id sh -> Id [sh]
forall (m :: * -> *) a. Monad m => Stream m a -> m [a]
SM.toList (Stream Id sh -> [elm]) -> Stream Id sh -> [elm]
forall a b. (a -> b) -> a -> b
$ LimitType sh -> LimitType sh -> Stream Id sh
forall i (m :: * -> *).
(IndexStream i, Monad m) =>
LimitType i -> LimitType i -> Stream m i
streamUp LimitType sh
forall i. Index i => LimitType i
zeroBound' LimitType sh
ub
{-# INLINE toList #-}