{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
module Data.Massiv.Array.Manifest.Storable
( S (..)
, Array(..)
, VS.Storable
, toStorableVector
, toStorableMVector
, fromStorableVector
, fromStorableMVector
, withPtr
, unsafeWithPtr
, unsafeArrayToForeignPtr
, unsafeMArrayToForeignPtr
, unsafeArrayFromForeignPtr
, unsafeArrayFromForeignPtr0
, unsafeMArrayFromForeignPtr
, unsafeMArrayFromForeignPtr0
) where
import Control.DeepSeq (NFData(..), deepseq)
import Control.Monad.IO.Unlift
import Control.Monad.Primitive (unsafePrimToPrim)
import Data.Massiv.Array.Delayed.Pull (eq, ord)
import Data.Massiv.Array.Manifest.Internal
import Data.Massiv.Array.Manifest.Primitive (shrinkMutableByteArray)
import Data.Primitive.ByteArray (MutableByteArray(..))
import Data.Massiv.Array.Manifest.List as A
import Data.Massiv.Vector.Stream as S (steps, isteps)
import Data.Massiv.Array.Mutable
import Data.Massiv.Core.Common
import Data.Massiv.Core.List
import qualified Data.Vector.Generic.Mutable as VGM
import qualified Data.Vector.Storable as VS
import qualified Data.Vector.Storable.Mutable as MVS
import Foreign.Ptr
import GHC.ForeignPtr (ForeignPtr(..), ForeignPtrContents(..))
import Foreign.ForeignPtr (withForeignPtr)
import Foreign.Storable
import Foreign.Marshal.Array (copyArray, advancePtr)
import GHC.Exts as GHC (IsList(..))
import Prelude hiding (mapM)
import System.IO.Unsafe (unsafePerformIO)
#include "massiv.h"
data S = S deriving Show
data instance Array S ix e = SArray { sComp :: !Comp
, sSize :: !(Sz ix)
, sData :: !(VS.Vector e)
}
instance (Ragged L ix e, Show e, VS.Storable e) => Show (Array S ix e) where
showsPrec = showsArrayPrec id
showList = showArrayList
instance NFData ix => NFData (Array S ix e) where
rnf (SArray c sz v) = c `deepseq` sz `deepseq` v `deepseq` ()
{-# INLINE rnf #-}
instance (VS.Storable e, Eq e, Index ix) => Eq (Array S ix e) where
(==) = eq (==)
{-# INLINE (==) #-}
instance (VS.Storable e, Ord e, Index ix) => Ord (Array S ix e) where
compare = ord compare
{-# INLINE compare #-}
instance (VS.Storable e, Index ix) => Construct S ix e where
setComp c arr = arr { sComp = c }
{-# INLINE setComp #-}
makeArray !comp !sz f = unsafePerformIO $ generateArray comp sz (return . f)
{-# INLINE makeArray #-}
instance (VS.Storable e, Index ix) => Source S ix e where
unsafeLinearIndex (SArray _ _ v) =
INDEX_CHECK("(Source S ix e).unsafeLinearIndex", Sz . VS.length, VS.unsafeIndex) v
{-# INLINE unsafeLinearIndex #-}
unsafeLinearSlice i k (SArray c _ v) = SArray c k $ VS.unsafeSlice i (unSz k) v
{-# INLINE unsafeLinearSlice #-}
instance Index ix => Resize S ix where
unsafeResize !sz !arr = arr { sSize = sz }
{-# INLINE unsafeResize #-}
instance (VS.Storable e, Index ix) => Extract S ix e where
unsafeExtract !sIx !newSz !arr = unsafeExtract sIx newSz (toManifest arr)
{-# INLINE unsafeExtract #-}
instance ( VS.Storable e
, Index ix
, Index (Lower ix)
, Elt M ix e ~ Array M (Lower ix) e
, Elt S ix e ~ Array M (Lower ix) e
) =>
OuterSlice S ix e where
unsafeOuterSlice arr = unsafeOuterSlice (toManifest arr)
{-# INLINE unsafeOuterSlice #-}
instance ( VS.Storable e
, Index ix
, Index (Lower ix)
, Elt M ix e ~ Array M (Lower ix) e
, Elt S ix e ~ Array M (Lower ix) e
) =>
InnerSlice S ix e where
unsafeInnerSlice arr = unsafeInnerSlice (toManifest arr)
{-# INLINE unsafeInnerSlice #-}
instance {-# OVERLAPPING #-} VS.Storable e => Slice S Ix1 e where
unsafeSlice arr i _ _ = pure (unsafeLinearIndex arr i)
{-# INLINE unsafeSlice #-}
instance (Index ix, VS.Storable e) => Manifest S ix e where
unsafeLinearIndexM (SArray _ _ v) =
INDEX_CHECK("(Manifest S ix e).unsafeLinearIndexM", Sz . VS.length, VS.unsafeIndex) v
{-# INLINE unsafeLinearIndexM #-}
instance (Index ix, VS.Storable e) => Mutable S ix e where
data MArray s S ix e = MSArray !(Sz ix) !(VS.MVector s e)
msize (MSArray sz _) = sz
{-# INLINE msize #-}
unsafeThaw (SArray _ sz v) = MSArray sz <$> VS.unsafeThaw v
{-# INLINE unsafeThaw #-}
unsafeFreeze comp (MSArray sz v) = SArray comp sz <$> VS.unsafeFreeze v
{-# INLINE unsafeFreeze #-}
unsafeNew sz = MSArray sz <$> MVS.unsafeNew (totalElem sz)
{-# INLINE unsafeNew #-}
initialize (MSArray _ marr) = VGM.basicInitialize marr
{-# INLINE initialize #-}
unsafeLinearRead (MSArray _ mv) =
INDEX_CHECK("(Mutable S ix e).unsafeLinearRead", Sz . MVS.length, MVS.unsafeRead) mv
{-# INLINE unsafeLinearRead #-}
unsafeLinearWrite (MSArray _ mv) =
INDEX_CHECK("(Mutable S ix e).unsafeLinearWrite", Sz . MVS.length, MVS.unsafeWrite) mv
{-# INLINE unsafeLinearWrite #-}
unsafeLinearSet (MSArray _ mv) i k = VGM.basicSet (MVS.unsafeSlice i (unSz k) mv)
{-# INLINE unsafeLinearSet #-}
unsafeLinearCopy marrFrom iFrom marrTo iTo (Sz k) = do
let MSArray _ (MVS.MVector _ fpFrom) = marrFrom
MSArray _ (MVS.MVector _ fpTo) = marrTo
unsafePrimToPrim $
withForeignPtr fpFrom $ \ ptrFrom ->
withForeignPtr fpTo $ \ ptrTo -> do
let ptrFrom' = advancePtr ptrFrom iFrom
ptrTo' = advancePtr ptrTo iTo
copyArray ptrTo' ptrFrom' k
{-# INLINE unsafeLinearCopy #-}
unsafeArrayLinearCopy arrFrom iFrom marrTo iTo sz = do
marrFrom <- unsafeThaw arrFrom
unsafeLinearCopy marrFrom iFrom marrTo iTo sz
{-# INLINE unsafeArrayLinearCopy #-}
unsafeLinearShrink marr@(MSArray _ mv@(MVS.MVector _ (ForeignPtr _ fpc))) sz = do
let shrinkMBA :: MutableByteArray RealWorld -> IO ()
shrinkMBA mba = shrinkMutableByteArray mba (totalElem sz * sizeOf (undefined :: e))
{-# INLINE shrinkMBA #-}
case fpc of
MallocPtr mba# _ -> do
unsafePrimToPrim $ shrinkMBA (MutableByteArray mba#)
pure $ MSArray sz mv
PlainPtr mba# -> do
unsafePrimToPrim $ shrinkMBA (MutableByteArray mba#)
pure $ MSArray sz mv
_ -> unsafeDefaultLinearShrink marr sz
{-# INLINE unsafeLinearShrink #-}
unsafeLinearGrow (MSArray oldSz mv) sz =
MSArray sz <$> MVS.unsafeGrow mv (totalElem sz - totalElem oldSz)
{-# INLINE unsafeLinearGrow #-}
instance (Index ix, VS.Storable e) => Load S ix e where
type R S = M
size = sSize
{-# INLINE size #-}
getComp = sComp
{-# INLINE getComp #-}
loadArrayM !scheduler !arr = splitLinearlyWith_ scheduler (elemsCount arr) (unsafeLinearIndex arr)
{-# INLINE loadArrayM #-}
instance (Index ix, VS.Storable e) => StrideLoad S ix e
instance (Index ix, VS.Storable e) => Stream S ix e where
toStream = S.steps
{-# INLINE toStream #-}
toStreamIx = S.isteps
{-# INLINE toStreamIx #-}
instance ( VS.Storable e
, IsList (Array L ix e)
, Nested LN ix e
, Nested L ix e
, Ragged L ix e
) =>
IsList (Array S ix e) where
type Item (Array S ix e) = Item (Array L ix e)
fromList = A.fromLists' Seq
{-# INLINE fromList #-}
toList = GHC.toList . toListArray
{-# INLINE toList #-}
unsafeWithPtr :: (MonadUnliftIO m, VS.Storable a) => Array S ix a -> (Ptr a -> m b) -> m b
unsafeWithPtr arr f = withRunInIO $ \run -> VS.unsafeWith (sData arr) (run . f)
{-# INLINE unsafeWithPtr #-}
withPtr :: (MonadUnliftIO m, VS.Storable a) => MArray RealWorld S ix a -> (Ptr a -> m b) -> m b
withPtr (MSArray _ mv) f = withRunInIO $ \run -> MVS.unsafeWith mv (run . f)
{-# INLINE withPtr #-}
toStorableVector :: Array S ix e -> VS.Vector e
toStorableVector = sData
{-# INLINE toStorableVector #-}
toStorableMVector :: MArray s S ix e -> VS.MVector s e
toStorableMVector (MSArray _ mv) = mv
{-# INLINE toStorableMVector #-}
fromStorableVector :: Storable e => Comp -> VS.Vector e -> Array S Ix1 e
fromStorableVector comp v = SArray {sComp = comp, sSize = SafeSz (VS.length v), sData = v}
{-# INLINE fromStorableVector #-}
fromStorableMVector :: MVS.MVector s e -> MArray s S Ix1 e
fromStorableMVector mv@(MVS.MVector len _) = MSArray (SafeSz len) mv
{-# INLINE fromStorableMVector #-}
unsafeArrayToForeignPtr :: VS.Storable e => Array S ix e -> (ForeignPtr e, Int)
unsafeArrayToForeignPtr = VS.unsafeToForeignPtr0 . toStorableVector
{-# INLINE unsafeArrayToForeignPtr #-}
unsafeMArrayToForeignPtr :: VS.Storable e => MArray s S ix e -> (ForeignPtr e, Int)
unsafeMArrayToForeignPtr = MVS.unsafeToForeignPtr0 . toStorableMVector
{-# INLINE unsafeMArrayToForeignPtr #-}
unsafeArrayFromForeignPtr0 :: VS.Storable e => Comp -> ForeignPtr e -> Sz1 -> Array S Ix1 e
unsafeArrayFromForeignPtr0 comp ptr sz =
SArray {sComp = comp, sSize = sz, sData = VS.unsafeFromForeignPtr0 ptr (unSz sz)}
{-# INLINE unsafeArrayFromForeignPtr0 #-}
unsafeArrayFromForeignPtr :: VS.Storable e => Comp -> ForeignPtr e -> Int -> Sz1 -> Array S Ix1 e
unsafeArrayFromForeignPtr comp ptr offset sz =
SArray {sComp = comp, sSize = sz, sData = VS.unsafeFromForeignPtr ptr offset (unSz sz)}
{-# INLINE unsafeArrayFromForeignPtr #-}
unsafeMArrayFromForeignPtr0 :: VS.Storable e => ForeignPtr e -> Sz1 -> MArray s S Ix1 e
unsafeMArrayFromForeignPtr0 fp sz =
MSArray sz (MVS.unsafeFromForeignPtr0 fp (unSz sz))
{-# INLINE unsafeMArrayFromForeignPtr0 #-}
unsafeMArrayFromForeignPtr :: VS.Storable e => ForeignPtr e -> Int -> Sz1 -> MArray s S Ix1 e
unsafeMArrayFromForeignPtr fp offset sz =
MSArray sz (MVS.unsafeFromForeignPtr fp offset (unSz sz))
{-# INLINE unsafeMArrayFromForeignPtr #-}