module Data.Repa.Array.Material.Boxed ( B (..) , Name (..) , Array (..) , Buffer (..) -- * Conversions , fromBoxed, toBoxed -- * Utils , decimate) where import Data.Repa.Array.Meta.Window as A import Data.Repa.Array.Generic.Index as A import Data.Repa.Array.Internals.Bulk as A import Data.Repa.Array.Internals.Target as A import Data.Word import Control.Monad import qualified Data.Vector as V import qualified Data.Vector.Mutable as VM #include "repa-array.h" -- | Layout an array as flat vector of boxed elements. -- -- UNSAFE: Indexing into raw material arrays is not bounds checked. -- You may want to wrap this with a Checked layout as well. -- data B = Boxed { boxedLength :: !Int } deriving (Show, Eq) ------------------------------------------------------------------------------ -- | Boxed arrays. instance Layout B where data Name B = B type Index B = Int name = B create B len = Boxed len extent (Boxed 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 B) deriving instance Show (Name B) ------------------------------------------------------------------------------ -- | Boxed arrays. instance Bulk B a where data Array B a = BArray !(V.Vector a) layout (BArray vec) = Boxed (V.length vec) index (BArray vec) ix = V.unsafeIndex vec ix {-# INLINE_ARRAY layout #-} {-# INLINE_ARRAY index #-} deriving instance Show a => Show (Array B a) instance Eq a => Eq (Array B a) where (==) (BArray arr1) (BArray arr2) = arr1 == arr2 {-# INLINE_ARRAY (==) #-} ------------------------------------------------------------------------------- -- | Boxed windows. instance Windowable B a where window st len (BArray vec) = BArray (V.unsafeSlice st len vec) {-# INLINE_ARRAY window #-} ------------------------------------------------------------------------------- -- | Boxed buffers. instance Target B a where data Buffer B a = BBuffer !(VM.IOVector a) unsafeNewBuffer (Boxed len) = liftM BBuffer (VM.unsafeNew len) {-# INLINE_ARRAY unsafeNewBuffer #-} unsafeReadBuffer (BBuffer mvec) ix = VM.unsafeRead mvec ix {-# INLINE_ARRAY unsafeReadBuffer #-} unsafeWriteBuffer (BBuffer mvec) ix = VM.unsafeWrite mvec ix {-# INLINE_ARRAY unsafeWriteBuffer #-} unsafeGrowBuffer (BBuffer mvec) bump = liftM BBuffer (VM.unsafeGrow mvec bump) {-# INLINE_ARRAY unsafeGrowBuffer #-} unsafeFreezeBuffer (BBuffer mvec) = liftM BArray (V.unsafeFreeze mvec) {-# INLINE_ARRAY unsafeFreezeBuffer #-} unsafeThawBuffer (BArray vec) = liftM BBuffer (V.unsafeThaw vec) {-# INLINE_ARRAY unsafeThawBuffer #-} unsafeSliceBuffer start len (BBuffer mvec) = let mvec' = VM.unsafeSlice start len mvec in return $ BBuffer mvec' {-# INLINE_ARRAY unsafeSliceBuffer #-} touchBuffer _ = return () {-# INLINE_ARRAY touchBuffer #-} bufferLayout (BBuffer mvec) = Boxed (VM.length mvec) {-# INLINE_ARRAY bufferLayout #-} {-# SPECIALIZE instance Target B Int #-} {-# SPECIALIZE instance Target B Float #-} {-# SPECIALIZE instance Target B Double #-} {-# SPECIALIZE instance Target B Word8 #-} {-# SPECIALIZE instance Target B Word16 #-} {-# SPECIALIZE instance Target B Word32 #-} {-# SPECIALIZE instance Target B Word64 #-} ------------------------------------------------------------------------------- -- | O(1). Wrap a boxed vector as an array. fromBoxed :: V.Vector a -> Array B a fromBoxed vec = BArray vec {-# INLINE_ARRAY fromBoxed #-} -- | O(1). Unwrap a boxed vector from an array. toBoxed :: Array B a -> V.Vector a toBoxed (BArray vec) = vec {-# INLINE_ARRAY toBoxed #-} -- | Scan through an array from front to back. -- For pairs of successive elements, drop the second one when the given -- predicate returns true. -- -- This function can be used to remove duplicates from a sorted array. -- -- TODO: generalise to other array types. decimate :: (a -> a -> Bool) -> Array B a -> Array B a decimate f arr | A.length arr == 0 = A.fromList B [] | otherwise = fromBoxed $ V.cons (arr `A.index` 0) (V.map snd $ V.filter (\(prev, here) -> not $ f prev here) $ V.zip (toBoxed arr) (V.tail $ toBoxed arr))