PrimitiveArray 0.1.1.2 → 0.2.0.0
raw patch · 7 files changed
+503/−136 lines, 7 filesdep −repaPVP ok
version bump matches the API change (PVP)
Dependencies removed: repa
API changes (from Hackage documentation)
- Data.PrimitiveArray: class (PrimMonad m, Shape sh) => PrimArrayOpsM sh elm m where { data family PrimArrayM sh elm m :: *; }
- Data.PrimitiveArray: unsafeFreezeM :: PrimArrayOpsM sh elm m => PrimArrayM sh elm m -> m (PrimArray sh elm)
- Data.PrimitiveArray: unsafeIndex :: PrimArrayOps sh elm => PrimArray sh elm -> sh -> elm
- Data.PrimitiveArray.Unboxed: instance (Read elm, Read sh, Unbox elm) => Read (PrimArray sh elm)
- Data.PrimitiveArray.Unboxed: instance (Show elm, Show sh, Unbox elm) => Show (PrimArray sh elm)
- Data.PrimitiveArray.Unboxed: instance (Unbox elm, Shape sh) => PrimArrayOpsM sh elm (ST s)
- Data.PrimitiveArray.Unboxed: instance (Unbox elm, Shape sh) => PrimArrayOpsM sh elm IO
- Data.PrimitiveArray.Unboxed: instance (Unbox elm, Shape sh, Show elm, Show sh) => PrimArrayOps sh elm
+ Data.Array.Repa.Index: (:.) :: tail -> head -> :. tail head
+ Data.Array.Repa.Index: Z :: Z
+ Data.Array.Repa.Index: data (:.) tail head
+ Data.Array.Repa.Index: data Z
+ Data.Array.Repa.Index: instance (Eq tail, Eq head) => Eq (tail :. head)
+ Data.Array.Repa.Index: instance (Ord tail, Ord head) => Ord (tail :. head)
+ Data.Array.Repa.Index: instance (Show tail, Show head) => Show (tail :. head)
+ Data.Array.Repa.Index: instance Eq Z
+ Data.Array.Repa.Index: instance Ord Z
+ Data.Array.Repa.Index: instance Shape Z
+ Data.Array.Repa.Index: instance Shape sh => Shape (sh :. Int)
+ Data.Array.Repa.Index: instance Show Z
+ Data.Array.Repa.Index: type DIM0 = Z
+ Data.Array.Repa.Index: type DIM1 = DIM0 :. Int
+ Data.Array.Repa.Index: type DIM2 = DIM1 :. Int
+ Data.Array.Repa.Index: type DIM3 = DIM2 :. Int
+ Data.Array.Repa.Index: type DIM4 = DIM3 :. Int
+ Data.Array.Repa.Index: type DIM5 = DIM4 :. Int
+ Data.Array.Repa.Shape: addDim :: Shape sh => sh -> sh -> sh
+ Data.Array.Repa.Shape: class Eq sh => Shape sh
+ Data.Array.Repa.Shape: deepSeq :: Shape sh => sh -> a -> a
+ Data.Array.Repa.Shape: fromIndex :: Shape sh => sh -> Int -> sh
+ Data.Array.Repa.Shape: inShape :: Shape sh => sh -> sh -> Bool
+ Data.Array.Repa.Shape: inShapeRange :: Shape sh => sh -> sh -> sh -> Bool
+ Data.Array.Repa.Shape: intersectDim :: Shape sh => sh -> sh -> sh
+ Data.Array.Repa.Shape: listOfShape :: Shape sh => sh -> [Int]
+ Data.Array.Repa.Shape: rank :: Shape sh => sh -> Int
+ Data.Array.Repa.Shape: shapeOfList :: Shape sh => [Int] -> sh
+ Data.Array.Repa.Shape: showShape :: Shape sh => sh -> String
+ Data.Array.Repa.Shape: size :: Shape sh => sh -> Int
+ Data.Array.Repa.Shape: sizeIsValid :: Shape sh => sh -> Bool
+ Data.Array.Repa.Shape: toIndex :: Shape sh => sh -> sh -> Int
+ Data.Array.Repa.Shape: unitDim :: Shape sh => sh
+ Data.Array.Repa.Shape: zeroDim :: Shape sh => sh
+ Data.ExtShape: class (Eq sh, Shape sh) => ExtShape sh
+ Data.ExtShape: instance ExtShape Z
+ Data.ExtShape: instance ExtShape sh => ExtShape (sh :. Int)
+ Data.ExtShape: rangeList :: ExtShape sh => sh -> sh -> [sh]
+ Data.ExtShape: subDim :: ExtShape sh => sh -> sh -> sh
+ Data.PrimitiveArray: class (Shape sh, ExtShape sh) => MPrimArrayOps marr sh elm
+ Data.PrimitiveArray: freeze :: (PrimArrayOps arr sh elm, PrimMonad m) => MutArray arr (PrimState m) sh elm -> m (arr sh elm)
+ Data.PrimitiveArray: fromList :: PrimArrayOps arr sh elm => sh -> sh -> [elm] -> arr sh elm
+ Data.PrimitiveArray: fromListM :: (MPrimArrayOps marr sh elm, PrimMonad m) => sh -> sh -> [elm] -> m (marr (PrimState m) sh elm)
+ Data.PrimitiveArray: index :: PrimArrayOps arr sh elm => arr sh elm -> sh -> elm
+ Data.PrimitiveArray: newM :: (MPrimArrayOps marr sh elm, PrimMonad m) => sh -> sh -> m (marr (PrimState m) sh elm)
+ Data.PrimitiveArray: newWithM :: (MPrimArrayOps marr sh elm, PrimMonad m) => sh -> sh -> elm -> m (marr (PrimState m) sh elm)
+ Data.PrimitiveArray: sliceEq :: (Eq elm, PrimArrayOps arr sh elm) => arr sh elm -> sh -> arr sh elm -> sh -> sh -> Bool
+ Data.PrimitiveArray: toList :: PrimArrayOps arr sh elm => arr sh elm -> [elm]
+ Data.PrimitiveArray.Unboxed.Zero: Arr0 :: !sh -> {-# UNPACK #-} !ByteArray -> Arr0 sh elm
+ Data.PrimitiveArray.Unboxed.Zero: MArr0 :: !sh -> {-# UNPACK #-} !MutableByteArray s -> MArr0 s sh elm
+ Data.PrimitiveArray.Unboxed.Zero: data Arr0 sh elm
+ Data.PrimitiveArray.Unboxed.Zero: data MArr0 s sh elm
+ Data.PrimitiveArray.Unboxed.Zero: instance (Shape sh, ExtShape sh, Prim elm) => MPrimArrayOps MArr0 sh elm
+ Data.PrimitiveArray.Unboxed.Zero: instance (Shape sh, ExtShape sh, Prim elm) => PrimArrayOps Arr0 sh elm
- Data.PrimitiveArray: (!) :: PrimArrayOps sh elm => PrimArray sh elm -> sh -> elm
+ Data.PrimitiveArray: (!) :: PrimArrayOps arr sh elm => arr sh elm -> sh -> elm
- Data.PrimitiveArray: assocs :: PrimArrayOps sh elm => PrimArray sh elm -> [(sh, elm)]
+ Data.PrimitiveArray: assocs :: PrimArrayOps arr sh elm => arr sh elm -> [(sh, elm)]
- Data.PrimitiveArray: bounds :: PrimArrayOps sh elm => PrimArray sh elm -> (sh, sh)
+ Data.PrimitiveArray: bounds :: PrimArrayOps arr sh elm => arr sh elm -> (sh, sh)
- Data.PrimitiveArray: boundsM :: PrimArrayOpsM sh elm m => PrimArrayM sh elm m -> (sh, sh)
+ Data.PrimitiveArray: boundsM :: MPrimArrayOps marr sh elm => marr s sh elm -> (sh, sh)
- Data.PrimitiveArray: class Shape sh => PrimArrayOps sh elm where { data family PrimArray sh elm :: *; }
+ Data.PrimitiveArray: class (Shape sh, ExtShape sh, MPrimArrayOps (MutArray arr) sh elm) => PrimArrayOps arr sh elm
- Data.PrimitiveArray: fromAssocs :: PrimArrayOps sh elm => sh -> sh -> elm -> [(sh, elm)] -> PrimArray sh elm
+ Data.PrimitiveArray: fromAssocs :: PrimArrayOps arr sh elm => sh -> sh -> elm -> [(sh, elm)] -> arr sh elm
- Data.PrimitiveArray: fromAssocsM :: PrimArrayOpsM sh elm m => sh -> sh -> elm -> [(sh, elm)] -> m (PrimArrayM sh elm m)
+ Data.PrimitiveArray: fromAssocsM :: (PrimMonad m, MPrimArrayOps marr sh elm) => sh -> sh -> elm -> [(sh, elm)] -> m (marr (PrimState m) sh elm)
- Data.PrimitiveArray: inBounds :: PrimArrayOps sh elm => PrimArray sh elm -> sh -> Bool
+ Data.PrimitiveArray: inBounds :: PrimArrayOps arr sh elm => arr sh elm -> sh -> Bool
- Data.PrimitiveArray: inBoundsM :: PrimArrayOpsM sh elm m => PrimArrayM sh elm m -> sh -> Bool
+ Data.PrimitiveArray: inBoundsM :: MPrimArrayOps marr sh elm => marr s sh elm -> sh -> Bool
- Data.PrimitiveArray: readM :: PrimArrayOpsM sh elm m => PrimArrayM sh elm m -> sh -> m elm
+ Data.PrimitiveArray: readM :: (MPrimArrayOps marr sh elm, PrimMonad m) => marr (PrimState m) sh elm -> sh -> m elm
- Data.PrimitiveArray: writeM :: PrimArrayOpsM sh elm m => PrimArrayM sh elm m -> sh -> elm -> m ()
+ Data.PrimitiveArray: writeM :: (MPrimArrayOps marr sh elm, PrimMonad m) => marr (PrimState m) sh elm -> sh -> elm -> m ()
Files
- Data/Array/Repa/Index.hs +145/−0
- Data/Array/Repa/Shape.hs +82/−0
- Data/ExtShape.hs +41/−0
- Data/PrimitiveArray.hs +147/−29
- Data/PrimitiveArray/Unboxed.hs +0/−97
- Data/PrimitiveArray/Unboxed/Zero.hs +70/−0
- PrimitiveArray.cabal +18/−10
+ Data/Array/Repa/Index.hs view
@@ -0,0 +1,145 @@+{-# LANGUAGE TypeOperators, FlexibleInstances, ScopedTypeVariables #-}++-- | Index types.+module Data.Array.Repa.Index+ (+ -- * Index types+ Z (..)+ , (:.) (..)++ -- * Common dimensions.+ , DIM0+ , DIM1+ , DIM2+ , DIM3+ , DIM4+ , DIM5)+where+import Data.Array.Repa.Shape+import GHC.Base (quotInt, remInt)++stage = "Data.Array.Repa.Index"++-- | An index of dimension zero+data Z = Z+ deriving (Show, Eq, Ord)++-- | Our index type, used for both shapes and indices.+infixl 3 :.+data tail :. head+ = tail :. head+ deriving (Show, Eq, Ord)++-- Common dimensions+type DIM0 = Z+type DIM1 = DIM0 :. Int+type DIM2 = DIM1 :. Int+type DIM3 = DIM2 :. Int+type DIM4 = DIM3 :. Int+type DIM5 = DIM4 :. Int+++-- Shape ------------------------------------------------------------------------------------------+instance Shape Z where+ {-# INLINE rank #-}+ rank _ = 0++ {-# INLINE zeroDim #-}+ zeroDim = Z++ {-# INLINE unitDim #-}+ unitDim = Z++ {-# INLINE intersectDim #-}+ intersectDim _ _ = Z++ {-# INLINE addDim #-}+ addDim _ _ = Z++ {-# INLINE size #-}+ size _ = 1++ {-# INLINE sizeIsValid #-}+ sizeIsValid _ = True+++ {-# INLINE toIndex #-}+ toIndex _ _ = 0++ {-# INLINE fromIndex #-}+ fromIndex _ _ = Z+++ {-# INLINE inShapeRange #-}+ inShapeRange Z Z Z = True++ listOfShape _ = []+ shapeOfList [] = Z+ shapeOfList _ = error $ stage ++ ".fromList: non-empty list when converting to Z."++ {-# INLINE deepSeq #-}+ deepSeq Z x = x+++instance Shape sh => Shape (sh :. Int) where+ {-# INLINE rank #-}+ rank (sh :. _)+ = rank sh + 1++ {-# INLINE zeroDim #-}+ zeroDim = zeroDim :. 0++ {-# INLINE unitDim #-}+ unitDim = unitDim :. 1++ {-# INLINE intersectDim #-}+ intersectDim (sh1 :. n1) (sh2 :. n2)+ = (intersectDim sh1 sh2 :. (min n1 n2))++ {-# INLINE addDim #-}+ addDim (sh1 :. n1) (sh2 :. n2)+ = addDim sh1 sh2 :. (n1 + n2)++ {-# INLINE size #-}+ size (sh1 :. n)+ = size sh1 * n++ {-# INLINE sizeIsValid #-}+ sizeIsValid (sh1 :. n)+ | size sh1 > 0+ = n <= maxBound `div` size sh1++ | otherwise+ = False++ {-# INLINE toIndex #-}+ toIndex (sh1 :. sh2) (sh1' :. sh2')+ = toIndex sh1 sh1' * sh2 + sh2'++ {-# INLINE fromIndex #-}+ fromIndex (ds :. d) n+ = fromIndex ds (n `quotInt` d) :. r+ where+ -- If we assume that the index is in range, there is no point+ -- in computing the remainder for the highest dimension since+ -- n < d must hold. This saves one remInt per element access which+ -- is quite a big deal.+ r | rank ds == 0 = n+ | otherwise = n `remInt` d++ {-# INLINE inShapeRange #-}+ inShapeRange (zs :. z) (sh1 :. n1) (sh2 :. n2)+ = (n2 >= z) && (n2 < n1) && (inShapeRange zs sh1 sh2)+++ listOfShape (sh :. n)+ = n : listOfShape sh++ shapeOfList xx+ = case xx of+ [] -> error $ stage ++ ".toList: empty list when converting to (_ :. Int)"+ x:xs -> shapeOfList xs :. x++ {-# INLINE deepSeq #-}+ deepSeq (sh :. n) x = deepSeq sh (n `seq` x)+
+ Data/Array/Repa/Shape.hs view
@@ -0,0 +1,82 @@+{-# LANGUAGE RankNTypes #-}++-- | Class of types that can be used as array shapes and indices.+module Data.Array.Repa.Shape+ ( Shape(..)+ , inShape+ , showShape )+where++-- Shape ------------------------------------------------------------------------------------------+-- | Class of types that can be used as array shapes and indices.+class Eq sh => Shape sh where++ -- | Get the number of dimensions in a shape.+ rank :: sh -> Int++ -- | The shape of an array of size zero, with a particular dimensionality.+ zeroDim :: sh++ -- | The shape of an array with size one, with a particular dimensionality.+ unitDim :: sh++ -- | Compute the intersection of two shapes.+ intersectDim :: sh -> sh -> sh++ -- | Add the coordinates of two shapes componentwise+ addDim :: sh -> sh -> sh++ -- | Get the total number of elements in an array with this shape.+ size :: sh -> Int++ -- | Check whether this shape is small enough so that its flat+ -- indices an be represented as `Int`. If this returns `False` then your+ -- array is too big. Mostly used for writing QuickCheck tests.+ sizeIsValid :: sh -> Bool+++ -- | Convert an index into its equivalent flat, linear, row-major version.+ toIndex :: sh -- ^ Shape of the array.+ -> sh -- ^ Index into the array.+ -> Int++ -- | Inverse of `toIndex`.+ fromIndex+ :: sh -- ^ Shape of the array.+ -> Int -- ^ Index into linear representation.+ -> sh++ -- | Check whether an index is within a given shape.+ inShapeRange+ :: sh -- ^ Start index for range.+ -> sh -- ^ Final index for range.+ -> sh -- ^ Index to check for.+ -> Bool++ -- | Convert a shape into its list of dimensions.+ listOfShape :: sh -> [Int]++ -- | Convert a list of dimensions to a shape+ shapeOfList :: [Int] -> sh++ -- | Ensure that a shape is completely evaluated.+ infixr 0 `deepSeq`+ deepSeq :: sh -> a -> a+++-- | Check whether an index is a part of a given shape.+inShape :: forall sh+ . Shape sh+ => sh -- ^ Shape of the array.+ -> sh -- ^ Index.+ -> Bool++{-# INLINE inShape #-}+inShape sh ix+ = inShapeRange zeroDim sh ix+++-- | Nicely format a shape as a string+showShape :: Shape sh => sh -> String+showShape = foldr (\sh str -> str ++ " :. " ++ show sh) "Z" . listOfShape+
+ Data/ExtShape.hs view
@@ -0,0 +1,41 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeOperators #-}++-- | Additional functions on shapes++module Data.ExtShape where++import Data.Array.Repa.Index+import Data.Array.Repa.Shape++++-- | A number of additional operations that are useful together with+-- 'PrimitiveArray's.++class (Eq sh, Shape sh) => ExtShape sh where++ -- | subtract the right coordinates from the left. Does not check if the+ -- resulting shape make sense.++ subDim :: sh -> sh -> sh++ -- | Given an index and an extend, return a list of all indices. For+ -- @rangeList (Z:.3) (Z:.2)@ this returns @[(Z:.3), (Z:.4), (Z:.5)]@.++ rangeList :: sh -> sh -> [sh]++++instance ExtShape Z where+ subDim _ _ = Z+ {-# INLINE subDim #-}+ rangeList _ _ = [Z]+ {-# INLINE rangeList #-}++instance ExtShape sh => ExtShape (sh:.Int) where+ subDim (sh1:.n1) (sh2:.n2) = subDim sh1 sh2 :. (n1-n2)+ {-# INLINE subDim #-}+ rangeList (sh1:.n1) (sh2:.n2) = [sh:.n | sh <- rangeList sh1 sh2, n <- [n1 .. (n1+n2) ] ]+ {-# INLINE rangeList #-}+
Data/PrimitiveArray.hs view
@@ -1,46 +1,164 @@-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-} --- | Primitive arrays with a small set of operations. Modelled after repa--- arrays and indexing.------ Array indexing is between [i..j] per dimension.+-- | Vastly extended primitive arrays. Some basic ideas are now modeled after+-- the vector package, especially the monadic mutable / pure immutable array+-- system. There are eight flavors of arrays among three axes: mutable/pure ++-- boxed/unboxed + zero-based/lower-bound. ----- All operations are UNSAFE. In interpreted code, "assert" provides a safety--- net.+-- NOTE all operations in MPrimArrayOps and PrimArrayOps are highly unsafe. No+-- bounds-checking is performed at all. module Data.PrimitiveArray where -import Control.Monad.Primitive (PrimMonad)-import Data.Array.Repa.Shape (Shape)+import Data.Array.Repa.Index+import Data.Array.Repa.Shape+import Data.Primitive.Types+import Data.Primitive+import Control.Monad.ST+import Control.Monad+import Control.Monad.Primitive+import System.IO.Unsafe import Control.Exception (assert) +import Data.ExtShape -class Shape sh => PrimArrayOps sh elm where- data PrimArray sh elm :: *- unsafeIndex :: PrimArray sh elm -> sh -> elm- bounds :: PrimArray sh elm -> (sh,sh)- inBounds :: PrimArray sh elm -> sh -> Bool- fromAssocs :: sh -> sh -> elm -> [(sh,elm)] -> PrimArray sh elm- assocs :: PrimArray sh elm -> [(sh,elm)] -class (PrimMonad m, Shape sh) => PrimArrayOpsM sh elm m where- data PrimArrayM sh elm m :: *- readM :: PrimArrayM sh elm m -> sh -> m elm- writeM :: PrimArrayM sh elm m -> sh -> elm -> m ()- -- | Create a monadic array from a list of associations- fromAssocsM :: sh -> sh -> elm -> [(sh,elm)] -> m (PrimArrayM sh elm m)- unsafeFreezeM :: PrimArrayM sh elm m -> m (PrimArray sh elm)- boundsM :: PrimArrayM sh elm m -> (sh,sh)- inBoundsM :: PrimArrayM sh elm m -> sh -> Bool+-- | The core set of operations for monadic arrays. +class (Shape sh, ExtShape sh) => MPrimArrayOps marr sh elm where + -- | Return the bounds of the array. All bounds are inclusive, as in+ -- @[lb..ub]@ --- * Helper functions+ boundsM :: marr s sh elm -> (sh,sh) -(!) :: PrimArrayOps sh elm => PrimArray sh elm -> sh -> elm-(!) pa idx = assert (inBounds pa idx) $ unsafeIndex pa idx+ -- | Given lower and upper bounds and a list of /all/ elements, produce a+ -- mutable array.++ fromListM :: PrimMonad m => sh -> sh -> [elm] -> m (marr (PrimState m) sh elm)++ -- | Creates a new array with the given bounds with each element within the+ -- array being in a random state.++ newM :: PrimMonad m => sh -> sh -> m (marr (PrimState m) sh elm)++ -- | Creates a new array with all elements being equal to 'elm'.++ newWithM :: PrimMonad m => sh -> sh -> elm -> m (marr (PrimState m) sh elm)++ -- | Reads a single element in the array.++ readM :: PrimMonad m => marr (PrimState m) sh elm -> sh -> m elm++ -- | Writes a single element in the array.++ writeM :: PrimMonad m => marr (PrimState m) sh elm -> sh -> elm -> m ()++++-- | Used to connect each immutable array with one mutable array.++type family MutArray (v :: * -> * -> * ) :: * -> * -> * -> *++++-- | The core set of functions on immutable arrays.++class (Shape sh, ExtShape sh, MPrimArrayOps (MutArray arr) sh elm) => PrimArrayOps arr sh elm where++ -- | Returns the bounds of an immutable array, again inclusive bounds: @ [lb..ub] @.++ bounds :: arr sh elm -> (sh,sh)++ -- | Freezes a mutable array an returns its immutable version. This operation+ -- is /O(1)/ and both arrays share the same memory. Do not use the mutable+ -- array afterwards.++ freeze :: PrimMonad m => MutArray arr (PrimState m) sh elm -> m (arr sh elm)++ -- | Extract a single element from the array. Generally unsafe as not+ -- bounds-checking is performed.++ index :: arr sh elm -> sh -> elm++++-- | Infix index operator. Performs minimal bounds-checking using assert in+-- non-optimized code.++(!) :: PrimArrayOps arr sh elm => arr sh elm -> sh -> elm+(!) arr idx = assert (inBounds arr idx) $ index arr idx {-# INLINE (!) #-}++-- | Returns true if the index is valid for the array.+--+-- TODO can't give a typedef++inBoundsM :: MPrimArrayOps marr sh elm => marr s sh elm -> sh -> Bool+inBoundsM marr idx = let (lb,ub) = boundsM marr in inShapeRange lb ub idx+{-# INLINE inBoundsM #-}++-- | Given two arrays with the same dimensionality, their respective starting+-- index, and how many steps to go in each dimension (in terms of a dimension+-- again), determine if the multidimensional slices have the same value at+-- all positions+--+-- TODO specialize for DIM1 (and maybe higher dim's) to use memcmp++sliceEq :: (Eq elm, PrimArrayOps arr sh elm) => arr sh elm -> sh -> arr sh elm -> sh -> sh -> Bool+sliceEq arr1 k1 arr2 k2 xtnd = assert ((inBounds arr1 k1) && (inBounds arr2 k2) && (inBounds arr1 $ k1 `addDim` xtnd) && (inBounds arr2 $ k2 `addDim` xtnd)) $ and res where+ res = zipWith (==) xs ys+ xs = map (index arr1) $ rangeList k1 xtnd+ ys = map (index arr2) $ rangeList k2 xtnd+{-# INLINE sliceEq #-}++-- | Construct a mutable primitive array from a lower and an upper bound, a+-- default element, and a list of associations.++fromAssocsM+ :: (PrimMonad m, MPrimArrayOps marr sh elm)+ => sh -> sh -> elm -> [(sh,elm)] -> m (marr (PrimState m) sh elm)+fromAssocsM lb ub def xs = do+ ma <- newWithM lb ub def+ forM_ xs $ \(k,v) -> writeM ma k v+ return ma+{-# INLINE fromAssocsM #-}++-- | Return all associations from an array.++assocs :: PrimArrayOps arr sh elm => arr sh elm -> [(sh,elm)]+assocs arr = map (\k -> (k,index arr k)) $ rangeList lb (ub `subDim` lb) where+ (lb,ub) = bounds arr+{-# INLINE assocs #-}++-- | Creates an immutable array from lower and upper bounds and a complete list+-- of elements.++fromList :: PrimArrayOps arr sh elm => sh -> sh -> [elm] -> arr sh elm+fromList lb ub xs = runST $ fromListM lb ub xs >>= freeze+{-# INLINE fromList #-}++-- | Creates an immutable array from lower and upper bounds, a default element,+-- and a list of associations.++fromAssocs :: PrimArrayOps arr sh elm => sh -> sh -> elm -> [(sh,elm)] -> arr sh elm+fromAssocs lb ub def xs = runST $ fromAssocsM lb ub def xs >>= freeze+{-# INLINE fromAssocs #-}++-- | Determines if an index is valid for a given immutable array.++inBounds :: PrimArrayOps arr sh elm => arr sh elm -> sh -> Bool+inBounds arr idx = let (lb,ub) = bounds arr in inShapeRange lb ub idx+{-# INLINE inBounds #-}++-- | Returns all elements of an immutable array as a list.++toList :: PrimArrayOps arr sh elm => arr sh elm -> [elm]+toList arr = let (lb,ub) = bounds arr in map ((!) arr) $ rangeList lb $ ub `subDim` lb+{-# INLINE toList #-}
− Data/PrimitiveArray/Unboxed.hs
@@ -1,97 +0,0 @@-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleInstances #-}--module Data.PrimitiveArray.Unboxed where--import qualified Data.Vector.Unboxed.Mutable as VUM-import qualified Data.Vector.Unboxed as VU-import Control.Monad.ST-import Control.Monad-import Data.Array.Repa.Shape-import Control.Exception (assert)--import Data.PrimitiveArray--import Data.Array.Repa.Index----instance (VU.Unbox elm, Shape sh, Show elm, Show sh) => PrimArrayOps sh elm where- -- | An immutable PrimArray has a lower bound (lsh), and upper bound (ush)- -- and an upper bound minus unitDim (ush'), returned by bounds- data PrimArray sh elm = PrimArray sh sh sh (VU.Vector elm)- unsafeIndex (PrimArray lsh ush ush' v) idx = assert (inShapeRange lsh ush idx)- $ v `VU.unsafeIndex` (toIndex ush idx - toIndex ush lsh)- bounds (PrimArray lsh ush ush' _) = (lsh,ush')- inBounds (PrimArray lsh ush ush' _) idx = inShapeRange lsh ush idx- fromAssocs lsh ush' def xs =- let ush = ush' `addDim` unitDim- in PrimArray lsh ush ush'- $ VU.replicate (size ush - size lsh) def- VU.// map (\(k,v) -> if (inShapeRange lsh ush k)- then (toIndex ush k - toIndex ush lsh,v)- else error $ show (lsh,ush,k,v)- ) xs- assocs (PrimArray lsh ush ush' v) = map (\(k,v) -> (fromIndex ush $ k + toIndex ush lsh, v))- . VU.toList- . VU.indexed- $ v- {-# INLINE unsafeIndex #-}- {-# INLINE bounds #-}- {-# INLINE inBounds #-}- {-# INLINE fromAssocs #-}--deriving instance (Show elm, Show sh, VU.Unbox elm) => Show (PrimArray sh elm)--deriving instance (Read elm, Read sh, VU.Unbox elm) => Read (PrimArray sh elm)----instance (VUM.Unbox elm, Shape sh) => PrimArrayOpsM sh elm (ST s) where- data PrimArrayM sh elm (ST s) = PrimArrayST sh sh sh (VUM.STVector s elm)- readM (PrimArrayST lsh ush ush' v) sh = VUM.unsafeRead v (toIndex ush sh - toIndex ush lsh)- writeM (PrimArrayST lsh ush suh' v) sh e = VUM.unsafeWrite v (toIndex ush sh - toIndex ush lsh) e- fromAssocsM lsh ush' def xs = do- let ush = ush' `addDim` unitDim- v <- VUM.new (size ush - size lsh)- VUM.set v def- forM_ xs $ \(k,e) -> assert (inShapeRange lsh ush k)- $ VUM.unsafeWrite v (toIndex ush k - toIndex ush lsh) e- return $ PrimArrayST lsh ush ush' v- unsafeFreezeM (PrimArrayST lsh ush ush' v) = do- v' <- VU.unsafeFreeze v- return $ PrimArray lsh ush ush' v'- boundsM (PrimArrayST lsh ush ush' _) = (lsh,ush')- inBoundsM (PrimArrayST lsh ush ush' _) idx = inShapeRange lsh ush idx- {-# INLINE readM #-}- {-# INLINE writeM #-}- {-# INLINE fromAssocsM #-}- {-# INLINE unsafeFreezeM #-}- {-# INLINE boundsM #-}- {-# INLINE inBoundsM #-}--instance (VUM.Unbox elm, Shape sh) => PrimArrayOpsM sh elm IO where- data PrimArrayM sh elm IO = PrimArrayIO sh sh sh (VUM.IOVector elm)- readM (PrimArrayIO lsh ush ush' v) sh = VUM.unsafeRead v (toIndex ush sh - toIndex ush lsh)- writeM (PrimArrayIO lsh ush suh' v) sh e = VUM.unsafeWrite v (toIndex ush sh - toIndex ush lsh) e- fromAssocsM lsh ush' def xs = do- let ush = ush' `addDim` unitDim- v <- VUM.new (size ush - size lsh)- VUM.set v def- forM_ xs $ \(k,e) -> assert (inShapeRange lsh ush k)- $ VUM.unsafeWrite v (toIndex ush k - toIndex ush lsh) e- return $ PrimArrayIO lsh ush ush' v- unsafeFreezeM (PrimArrayIO lsh ush ush' v) = do- v' <- VU.unsafeFreeze v- return $ PrimArray lsh ush ush' v'- boundsM (PrimArrayIO lsh ush ush' _) = (lsh,ush')- inBoundsM (PrimArrayIO lsh ush ush' _) idx = inShapeRange lsh ush idx- {-# INLINE readM #-}- {-# INLINE writeM #-}- {-# INLINE fromAssocsM #-}- {-# INLINE unsafeFreezeM #-}- {-# INLINE boundsM #-}- {-# INLINE inBoundsM #-}-
+ Data/PrimitiveArray/Unboxed/Zero.hs view
@@ -0,0 +1,70 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}++-- | Strict, unboxed arrays of primitive type.++module Data.PrimitiveArray.Unboxed.Zero where++import Control.Monad+import Data.Array.Repa.Index+import Data.Array.Repa.Shape+import Data.Primitive+import Data.Primitive.Types+import Control.Exception (assert)++import Data.ExtShape+import Data.PrimitiveArray++++-- | Monadic arrays of primitive type.++data MArr0 s sh elm = MArr0 !sh {-# UNPACK #-} !(MutableByteArray s)++-- | Immutable arrays of primitive type.++data Arr0 sh elm = Arr0 !sh {-# UNPACK #-} !ByteArray++++type instance MutArray Arr0 = MArr0++-- NOTE inLb, inUb is including bound, while exUb is excluding upper bound.+-- Differentiates between largest included index, first excluded index.++instance (Shape sh, ExtShape sh, Prim elm) => MPrimArrayOps MArr0 sh elm where+ boundsM (MArr0 exUb _) = (zeroDim,exUb `subDim` unitDim)+ fromListM inLb inUb xs = do+ ma <- newM inLb inUb+ let exUb = inUb `addDim` unitDim+ let (MArr0 _ mba) = ma+ zipWithM_ (\k x -> assert (length xs == size exUb) $ writeByteArray mba k x) [0.. toIndex exUb inUb] xs+ return ma+ newM inLb inUb = let exUb = inUb `addDim` unitDim in+ unless (inLb == zeroDim) (error "MArr0 lb/=zeroDim") >>+ MArr0 exUb `liftM` newByteArray (size exUb * sizeOf (undefined :: elm))+ newWithM inLb inUb def = do+ let exUb = inUb `addDim` unitDim+ ma <- newM inLb inUb+ let (MArr0 _ mba) = ma+ forM_ [0 .. toIndex exUb inUb] $ \k -> writeByteArray mba k def+ return ma+ readM (MArr0 exUb mba) idx = assert (inShape exUb idx) $ readByteArray mba (toIndex exUb idx)+ writeM (MArr0 exUb mba) idx elm = assert (inShape exUb idx) $ writeByteArray mba (toIndex exUb idx) elm+ {-# INLINE boundsM #-}+ {-# INLINE fromListM #-}+ {-# INLINE newM #-}+ {-# INLINE newWithM #-}+ {-# INLINE readM #-}+ {-# INLINE writeM #-}++instance (Shape sh, ExtShape sh, Prim elm) => PrimArrayOps Arr0 sh elm where+ bounds (Arr0 exUb _) = (zeroDim,exUb `subDim` unitDim)+ freeze (MArr0 exUb mba) = Arr0 exUb `liftM` unsafeFreezeByteArray mba+ index (Arr0 exUb ba) idx = assert (inShape exUb idx) $ indexByteArray ba (toIndex exUb idx)+ {-# INLINE bounds #-}+ {-# INLINE freeze #-}+ {-# INLINE index #-}+
PrimitiveArray.cabal view
@@ -1,5 +1,5 @@ Name: PrimitiveArray-Version: 0.1.1.2+Version: 0.2.0.0 License: BSD3 License-file: LICENSE Author: Christian Hoener zu Siederdissen@@ -13,26 +13,34 @@ Synopsis: Efficient multidimensional arrays Description:- This library provides efficient multidimensional arrays. All- arrays are 0-based and indexed using repa-shapes.+ This library provides efficient multidimensional arrays. .- Please note that this version only has the name (and author) in- common with the previous 0.0.4.0 version. The basic idea of the- library remains the same: provide efficient access to immutable- arrays.+ In general all operations are (highly) unsafe, no+ bounds-checking or other sanity-checking is performed.+ Operations are aimed toward efficiency as much as possible.+ Goals of the library are to have arrays according to three+ ideas: immutable/mutable arrays, strict/lazy arrays,+ zero-based/lower-bound arrays. Zero-based arrays save one+ addition on each access if the lower bound or the array is+ always zero.+ .+ We have forked two repa modules: Shape and Index. Library Exposed-modules:+ Data.Array.Repa.Index+ Data.Array.Repa.Shape+ Data.ExtShape Data.PrimitiveArray- Data.PrimitiveArray.Unboxed+ Data.PrimitiveArray.Unboxed.Zero Build-depends: base >= 4 && <5, primitive >= 0.4,- vector >= 0.9,- repa >= 2.0+ vector >= 0.9 ghc-options: -Odph -funbox-strict-fields+ source-repository head type: git