content: 
  {-# 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  #-}
  