repa-array-4.2.2.1: Data/Repa/Array/Material/Foreign/Base.hs
module Data.Repa.Array.Material.Foreign.Base
( F (..)
, Name (..)
, Array (..)
, Buffer (..)
-- * Conversions
, unsafeCast
, fromForeignPtr, toForeignPtr
, fromStorableVector, toStorableVector
, fromByteString, toByteString)
where
import Data.Repa.Array.Meta.Delayed as A
import Data.Repa.Array.Meta.Window as A
import Data.Repa.Array.Generic.Index as A
import Data.Repa.Array.Internals.Target as A
import Data.Repa.Array.Internals.Bulk as A
import Foreign.ForeignPtr
import Foreign.Storable
import Control.Monad
import Control.Monad.Primitive
import Data.Word
import Data.ByteString (ByteString)
import qualified Data.ByteString.Internal as BS
import qualified Data.Vector.Storable as S
import qualified Data.Vector.Storable.Mutable as M
#include "repa-array.h"
-- | Layout for dense Foreign arrays.
--
-- UNSAFE: Indexing into raw material arrays is not bounds checked.
-- You may want to wrap this with a Checked layout as well.
--
data F = Foreign { foreignLength :: Int }
deriving (Show, Eq)
------------------------------------------------------------------------------
-- | Foreign arrays.
instance Layout F where
data Name F = F
type Index F = Int
name = F
create F len = Foreign len
extent (Foreign len) = len
toIndex _ ix = ix
fromIndex _ ix = ix
{-# INLINE_ARRAY name #-}
{-# INLINE_ARRAY create #-}
{-# INLINE_ARRAY extent #-}
{-# INLINE_ARRAY toIndex #-}
{-# INLINE_ARRAY fromIndex #-}
deriving instance Eq (Name F)
deriving instance Show (Name F)
-------------------------------------------------------------------------------
-- | Foreign arrays.
instance Storable a => Bulk F a where
data Array F a = FArray !(S.Vector a)
layout (FArray v) = Foreign (S.length v)
index (FArray v) i = S.unsafeIndex v i
{-# INLINE_ARRAY layout #-}
{-# INLINE_ARRAY index #-}
{-# SPECIALIZE instance Bulk F Char #-}
{-# SPECIALIZE instance Bulk F Int #-}
{-# SPECIALIZE instance Bulk F Float #-}
{-# SPECIALIZE instance Bulk F Double #-}
{-# SPECIALIZE instance Bulk F Word8 #-}
{-# SPECIALIZE instance Bulk F Word16 #-}
{-# SPECIALIZE instance Bulk F Word32 #-}
{-# SPECIALIZE instance Bulk F Word64 #-}
deriving instance (S.Storable a, Show a) => Show (Array F a)
-------------------------------------------------------------------------------
-- | Windowing Foreign arrays.
instance Storable a => Windowable F a where
window st len (FArray vec)
= FArray (S.unsafeSlice st len vec)
{-# INLINE_ARRAY window #-}
{-# SPECIALIZE instance Windowable F Char #-}
{-# SPECIALIZE instance Windowable F Int #-}
{-# SPECIALIZE instance Windowable F Float #-}
{-# SPECIALIZE instance Windowable F Double #-}
{-# SPECIALIZE instance Windowable F Word8 #-}
{-# SPECIALIZE instance Windowable F Word16 #-}
{-# SPECIALIZE instance Windowable F Word32 #-}
{-# SPECIALIZE instance Windowable F Word64 #-}
-------------------------------------------------------------------------------
-- | Foreign buffers
instance Storable a => Target F a where
data Buffer F a = FBuffer !(M.IOVector a)
unsafeNewBuffer (Foreign n) = FBuffer `liftM` M.unsafeNew n
unsafeReadBuffer (FBuffer mv) i = M.unsafeRead mv i
unsafeWriteBuffer (FBuffer mv) i a = M.unsafeWrite mv i a
unsafeGrowBuffer (FBuffer mv) x = FBuffer `liftM` M.unsafeGrow mv x
unsafeThawBuffer (FArray v) = FBuffer `liftM` S.unsafeThaw v
unsafeFreezeBuffer (FBuffer mv) = FArray `liftM` S.unsafeFreeze mv
unsafeSliceBuffer i n (FBuffer mv) = return $ FBuffer (M.unsafeSlice i n mv)
touchBuffer (FBuffer (M.MVector _ p)) = unsafePrimToPrim $ touchForeignPtr p
bufferLayout (FBuffer mv) = Foreign $ M.length mv
{-# INLINE unsafeNewBuffer #-}
{-# INLINE unsafeWriteBuffer #-}
{-# INLINE unsafeReadBuffer #-}
{-# INLINE unsafeGrowBuffer #-}
{-# INLINE unsafeThawBuffer #-}
{-# INLINE unsafeFreezeBuffer #-}
{-# INLINE unsafeSliceBuffer #-}
{-# INLINE touchBuffer #-}
{-# INLINE bufferLayout #-}
-------------------------------------------------------------------------------
-- | O(1). Cast a foreign array from one element type to another.
unsafeCast
:: (Storable a, Storable b)
=> Array F a -> Array F b
unsafeCast (FArray vec)
= FArray $ S.unsafeCast vec
{-# INLINE_ARRAY unsafeCast #-}
-- | O(1). Wrap a `ForeignPtr` as an array.
fromForeignPtr :: Storable a => Int -> ForeignPtr a -> Array F a
fromForeignPtr n p = FArray $ S.unsafeFromForeignPtr p 0 n
{-# INLINE_ARRAY fromForeignPtr #-}
-- | O(1). Unwrap a `ForeignPtr` from an array.
toForeignPtr :: Storable a => Array F a -> (Int, Int, ForeignPtr a)
toForeignPtr (FArray (S.unsafeToForeignPtr -> (p,i,n))) = (i,n,p)
{-# INLINE_ARRAY toForeignPtr #-}
-- | O(1). Convert a foreign array to a storable `Vector`.
toStorableVector :: Array F a -> S.Vector a
toStorableVector (FArray vec) = vec
{-# INLINE_ARRAY toStorableVector #-}
-- | O(1). Convert a storable `Vector` to a foreign `Array`
fromStorableVector :: S.Vector a -> Array F a
fromStorableVector vec = FArray vec
{-# INLINE_ARRAY fromStorableVector #-}
-- | O(1). Convert a foreign 'Vector' to a `ByteString`.
toByteString :: Array F Word8 -> ByteString
toByteString (FArray (S.unsafeToForeignPtr -> (p,i,n)))
= BS.PS p i n
{-# INLINE_ARRAY toByteString #-}
-- | O(1). Convert a `ByteString` to an foreign `Array`.
fromByteString :: ByteString -> Array F Word8
fromByteString (BS.PS p i n)
= FArray (S.unsafeFromForeignPtr p i n)
{-# INLINE_ARRAY fromByteString #-}
instance (Eq a, Storable a) => Eq (Array F a) where
(FArray a1) == (FArray a2) = a1 == a2
{-# INLINE_ARRAY (==) #-}