{-# LANGUAGE TypeFamilies,FlexibleInstances,MultiParamTypeClasses,FlexibleContexts #-} {-# LANGUAGE UndecidableInstances,StandaloneDeriving, DeriveDataTypeable #-} {-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable, DeriveGeneric #-} {-# LANGUAGE CPP #-} module Numerical.Array.Storage( Boxed ,Unboxed ,Stored ,BufferPure(..) ,BufferMut(..) ,Buffer ,MBuffer ,unsafeBufferThaw ,unsafeBufferFreeze) where import Control.Monad.Primitive ( PrimMonad, PrimState ) import qualified Data.Vector.Generic as VG import qualified Data.Vector.Generic.Mutable as VGM import qualified Data.Vector as BV import qualified Data.Vector.Storable as SV import qualified Data.Vector.Unboxed as UV --import qualified Data.Functor as F hiding (Functor) --import qualified Data.Foldable as F hiding (Foldable) --import qualified Data.Traversable as T hiding (Traversable) #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ < 709 --import Data.Functor (Functor) import Data.Foldable (Foldable) import Data.Traversable (Traversable) #endif import Data.Typeable import Data.Data import GHC.Generics {- FIXME : should i require that the element type and mode are both instance of Typeable for Buffers? -} {- FIX MEEEEE REMINDERS make the allocators for Storable Buffers do AVX sized alignment -} -- | The class instance @'Buffer' mode a@ is a shorthand for saying that a given buffer representation @mode@ -- has a 'VG.Vector' instance for both 'BufferPure' and 'BufferMut'. class (VG.Vector (BufferPure mode) a, VGM.MVector (BufferMut mode) a)=> Buffer mode a instance (VG.Vector (BufferPure mode) a, VGM.MVector (BufferMut mode) a)=> Buffer mode a -- not sure if MBuffer class should exist, fixme. if/when removed, this class VGM.MVector (BufferMut mode) a=> MBuffer mode a -- not sure if MBuffer should exist, FIXME instance VGM.MVector (BufferMut mode) a=> MBuffer mode a -- | 'Boxed' is the type index for `Buffer`s that use the boxed data structure `Data.Vector.Vector` -- as the underlying storage representation. data Boxed deriving Typeable deriving instance Data Boxed -- | 'Unboxed' is the type index for 'Buffer's that use the unboxed data structure -- 'Data.Vector.Unboxed.Vector' as the underlying storage representation. data Unboxed deriving Typeable deriving instance Data Unboxed -- | 'Stored' is the type index for 'Buffer's that use the 'Foreign.Storable' -- for values, in pinned byte array buffers, provided by 'Data.Vector.Storable' data Stored deriving Typeable deriving instance Data Stored type instance VG.Mutable (BufferPure sort) = BufferMut sort data family BufferPure sort elem deriving instance Typeable BufferPure newtype instance BufferPure Boxed elem = BoxedBuffer (BV.Vector elem) deriving (Show,Data,Generic,Functor,Foldable,Traversable) newtype instance BufferPure Unboxed elem = UnboxedBuffer (UV.Vector elem) deriving (Show,Data,Generic) --deriving instance Typeable a => Typeable (BufferPure Unboxed a) newtype instance BufferPure Stored elem = StorableBuffer (SV.Vector elem) deriving (Show,Data,Generic) data family BufferMut sort st elem deriving instance Typeable BufferMut newtype instance BufferMut Boxed st elem = BoxedBufferMut (BV.MVector st elem) --deriving (Show,Data,Generic) newtype instance BufferMut Unboxed st elem = UnboxedBufferMut (UV.MVector st elem) --deriving (Show,Data,Generic) newtype instance BufferMut Stored st elem = StorableBufferMut (SV.MVector st elem) -- | 'unsafeBufferFreeze' unsafeBufferFreeze :: (Buffer rep a,PrimMonad m) => BufferMut rep (PrimState m ) a -> m (BufferPure rep a) unsafeBufferFreeze = VG.basicUnsafeFreeze unsafeBufferThaw :: (Buffer rep a,PrimMonad m) => (BufferPure rep a) -> m (BufferMut rep (PrimState m ) a) unsafeBufferThaw = VG.basicUnsafeThaw instance (VGM.MVector BV.MVector elem) => VGM.MVector (BufferMut Boxed) elem where basicInitialize = \(BoxedBufferMut v) -> VGM.basicInitialize v basicLength = \(BoxedBufferMut v) -> VGM.basicLength v basicUnsafeSlice = \ ix1 ix2 (BoxedBufferMut bv) -> BoxedBufferMut $ VGM.basicUnsafeSlice ix1 ix2 bv basicOverlaps = \ (BoxedBufferMut bv1) (BoxedBufferMut bv2) -> VGM.basicOverlaps bv1 bv2 basicUnsafeNew = \ size -> do res<- VGM.basicUnsafeNew size return (BoxedBufferMut res) basicUnsafeRead= \(BoxedBufferMut bv) ix -> VGM.basicUnsafeRead bv ix basicUnsafeWrite = \(BoxedBufferMut bv ) ix val -> VGM.basicUnsafeWrite bv ix val {-Q/todo/check fixme, do these other operations need be provided in a pass through way too? or will there be no difference in the derived code perf ? -} -- basicUnsafeClear -- basicUnsafeSet -- basicUnsafeCopy -- basicUnsafeMove -- basicUnsafeGrow -- basicUnsafeReplicate {-# INLINE basicInitialize #-} {-# INLINE basicLength #-} {-# INLINE basicUnsafeSlice #-} {-# INLINE basicOverlaps #-} {-# INLINE basicUnsafeNew #-} {-# INLINE basicUnsafeRead #-} {-# INLINE basicUnsafeWrite #-} -- {-# INLINE basicUnsafeClear#-} -- {-# INLINE basicUnsafeSet#-} -- {-# INLINE basicUnsafeCopy#-} -- {-# INLINE basicUnsafeMove#-} -- {-# INLINE basicUnsafeGrow#-} -- {-# INLINE basicUnsafeReplicate#-} instance (SV.Storable elem) => VGM.MVector (BufferMut Stored) elem where basicInitialize = \(StorableBufferMut v) -> VGM.basicInitialize v basicLength = \(StorableBufferMut v) -> VGM.basicLength v basicUnsafeSlice = \ ix1 ix2 (StorableBufferMut bv) -> StorableBufferMut $ VGM.basicUnsafeSlice ix1 ix2 bv basicOverlaps = \ (StorableBufferMut bv1) (StorableBufferMut bv2) -> VGM.basicOverlaps bv1 bv2 basicUnsafeNew = \ size -> do res<- VGM.basicUnsafeNew size return (StorableBufferMut res) basicUnsafeRead= \(StorableBufferMut bv) ix -> VGM.basicUnsafeRead bv ix basicUnsafeWrite = \(StorableBufferMut bv ) ix val -> VGM.basicUnsafeWrite bv ix val {-# INLINE basicInitialize #-} {-# INLINE basicLength #-} {-# INLINE basicUnsafeSlice #-} {-# INLINE basicOverlaps #-} {-# INLINE basicUnsafeNew #-} {-# INLINE basicUnsafeRead #-} {-# INLINE basicUnsafeWrite #-} instance (VGM.MVector UV.MVector elem) => VGM.MVector (BufferMut Unboxed) elem where {-# INLINE basicInitialize #-} basicInitialize = \(UnboxedBufferMut v) -> VGM.basicInitialize v basicLength = \(UnboxedBufferMut v) -> VGM.basicLength v basicUnsafeSlice = \ ix1 ix2 (UnboxedBufferMut bv) -> UnboxedBufferMut $ VGM.basicUnsafeSlice ix1 ix2 bv basicOverlaps = \ (UnboxedBufferMut bv1) (UnboxedBufferMut bv2) -> VGM.basicOverlaps bv1 bv2 basicUnsafeNew = \ size -> do res<- VGM.basicUnsafeNew size return (UnboxedBufferMut res) basicUnsafeRead= \(UnboxedBufferMut bv) ix -> VGM.basicUnsafeRead bv ix basicUnsafeWrite = \(UnboxedBufferMut bv ) ix val -> VGM.basicUnsafeWrite bv ix val {-# INLINE basicLength #-} {-# INLINE basicUnsafeSlice #-} {-# INLINE basicOverlaps #-} {-# INLINE basicUnsafeNew #-} {-# INLINE basicUnsafeRead #-} {-# INLINE basicUnsafeWrite #-} ---- ---- instance VG.Vector BV.Vector a => VG.Vector (BufferPure Boxed) a where basicUnsafeFreeze = \(BoxedBufferMut mv) ->(\ x->return $ BoxedBuffer x) =<< VG.basicUnsafeFreeze mv basicUnsafeThaw= \(BoxedBuffer v) ->(\x -> return $ BoxedBufferMut x ) =<< VG.basicUnsafeThaw v basicLength = \(BoxedBuffer v) -> VG.basicLength v basicUnsafeSlice = \ start len (BoxedBuffer v) -> BoxedBuffer $! VG.basicUnsafeSlice start len v basicUnsafeIndexM = \ (BoxedBuffer v) ix -> VG.basicUnsafeIndexM v ix elemseq = \ (BoxedBuffer v) a b -> VG.elemseq v a b {-# INLINE basicUnsafeFreeze #-} {-# INLINE basicUnsafeThaw #-} {-# INLINE basicLength #-} {-# INLINE basicUnsafeSlice #-} {-# INLINE basicUnsafeIndexM #-} {-# INLINE elemseq #-} instance (SV.Storable a) => VG.Vector (BufferPure Stored) a where basicUnsafeFreeze = \(StorableBufferMut mv) -> (\x ->return $StorableBuffer x) =<< VG.basicUnsafeFreeze mv basicUnsafeThaw= \(StorableBuffer v) -> (\x -> return $ StorableBufferMut x) =<< VG.basicUnsafeThaw v basicLength = \(StorableBuffer v) -> VG.basicLength v basicUnsafeSlice = \ start len (StorableBuffer v) -> StorableBuffer $! VG.basicUnsafeSlice start len v basicUnsafeIndexM = \ (StorableBuffer v) ix -> VG.basicUnsafeIndexM v ix elemseq = \ (StorableBuffer v) a b -> VG.elemseq v a b {-# INLINE basicUnsafeFreeze #-} {-# INLINE basicUnsafeThaw #-} {-# INLINE basicLength #-} {-# INLINE basicUnsafeSlice #-} {-# INLINE basicUnsafeIndexM #-} {-# INLINE elemseq #-} instance VG.Vector UV.Vector a => VG.Vector (BufferPure Unboxed) a where basicUnsafeFreeze = \(UnboxedBufferMut mv) -> (\x -> return $ UnboxedBuffer x) =<< VG.basicUnsafeFreeze mv basicUnsafeThaw= \(UnboxedBuffer v) ->(\x -> return $ UnboxedBufferMut x) =<< VG.basicUnsafeThaw v basicLength = \(UnboxedBuffer v) -> VG.basicLength v basicUnsafeSlice = \ start len (UnboxedBuffer v) -> UnboxedBuffer $! VG.basicUnsafeSlice start len v basicUnsafeIndexM = \ (UnboxedBuffer v) ix -> VG.basicUnsafeIndexM v ix elemseq = \ (UnboxedBuffer v) a b -> VG.elemseq v a b {-# INLINE basicUnsafeFreeze #-} {-# INLINE basicUnsafeThaw #-} {-# INLINE basicLength #-} {-# INLINE basicUnsafeSlice #-} {-# INLINE basicUnsafeIndexM #-} {-# INLINE elemseq #-}