dense 0.1.0.0 → 0.1.0.1
raw patch · 7 files changed
+90/−68 lines, 7 filesdep ~lineardep ~vector
Dependency ranges changed: linear, vector
Files
- README.md +1/−1
- dense.cabal +4/−4
- src/Data/Dense/Base.hs +1/−0
- src/Data/Dense/Generic.hs +11/−1
- src/Data/Dense/Index.hs +32/−29
- src/Data/Dense/Mutable.hs +30/−30
- src/Data/Dense/TH.hs +11/−3
README.md view
@@ -1,6 +1,6 @@ ## dense -[](https://travis-ci.org/cchalmers/dense)+[](https://travis-ci.org/cchalmers/dense) [](https://cchalmers.github.io/dense/) [](https://hackage.haskell.org/package/dense)
dense.cabal view
@@ -1,5 +1,5 @@ name: dense-version: 0.1.0.0+version: 0.1.0.1 synopsis: Mutable and immutable dense multidimensional arrays description: Multidimentional array library build on top of the vector package,@@ -46,13 +46,13 @@ ghc-prim, hashable, lens,- linear >= 1.20 && <1.21,+ linear >= 1.20 && <1.22, primitive, semigroupoids, template-haskell, transformers, transformers-compat,- vector+ vector >= 0.12 && < 0.13 hs-source-dirs: src ghc-options: -Wall default-language: Haskell2010@@ -72,7 +72,7 @@ ghc-prim, hashable, lens,- linear >= 1.20 && <1.21,+ linear >= 1.20 && <1.22, primitive, semigroupoids, template-haskell,
src/Data/Dense/Base.hs view
@@ -11,6 +11,7 @@ {-# LANGUAGE RankNTypes #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-} ----------------------------------------------------------------------------- -- | -- Module : Data.Dense.Base
src/Data/Dense/Generic.hs view
@@ -72,6 +72,7 @@ -- ** Monadic initialisation , create+ , createT , replicateM , generateM , linearGenerateM@@ -213,6 +214,7 @@ import Data.Functor.Classes import qualified Data.List as L import Data.Maybe (fromMaybe)+import qualified Data.Traversable as T import Data.Typeable import qualified Data.Vector as B import Data.Vector.Fusion.Bundle (MBundle)@@ -410,6 +412,14 @@ create m = m `seq` runST (m >>= unsafeFreeze) {-# INLINE create #-} +-- | Execute the monadic action and freeze the resulting array.+createT+ :: (Vector v a, Traversable t)+ => (forall s . ST s (t (MArray (G.Mutable v) f s a)))+ -> t (Array v f a)+createT m = m `seq` runST (m >>= T.mapM unsafeFreeze)+{-# INLINE createT #-}+ -- | O(n) Array of the given shape with the same value in each position. replicate :: (Shape f, Vector v a) => f Int -> a -> Array v f a replicate l a@@ -611,7 +621,7 @@ -> Array v f b -> Array v f c zipWith f a1@(Array l1 v1) a2@(Array l2 v2)- | eq1 l1 l1 = Array l1 $ G.zipWith f v1 v2+ | eq1 l1 l2 = Array l1 $ G.zipWith f v1 v2 | otherwise = Array l' $ G.unstream $ MBundle.fromStream (Stream.zipWith f (streamSub l' a1) (streamSub l' a2)) (Exact (shapeSize l')) where l' = shapeIntersect l1 l2
src/Data/Dense/Index.hs view
@@ -81,12 +81,12 @@ class (Eq1 f, Additive f, Traversable f) => Shape f where -- | Convert a shape to its linear index using the 'Layout'. shapeToIndex :: Layout f -> f Int -> Int- shapeToIndex l x = F.foldl (\k (e, a) -> k * e + a) 0 (liftI2 (,) l x)+ shapeToIndex l x = F.foldr (\(e, a) k -> a + e*k) 0 (liftI2 (,) l x) {-# INLINE shapeToIndex #-} -- | Convert a linear index to a shape the 'Layout'. shapeFromIndex :: Layout f -> Int -> f Int- shapeFromIndex l i = snd $ mapAccumR quotRem i l+ shapeFromIndex l i = snd $ mapAccumL quotRem i l {-# INLINE shapeFromIndex #-} -- | Calculate the intersection of two shapes.@@ -148,59 +148,62 @@ shapeInRange m i = i >= 0 && i < m instance Shape V2 where- shapeToIndex (V2 _x y) (V2 i j) = y*i + j+ shapeToIndex (V2 x _y) (V2 i j) = i + x*j {-# INLINE shapeToIndex #-} - shapeFromIndex (V2 _x y) n = V2 i j- where (i, j) = n `quotRem` y+ shapeFromIndex (V2 x _y) n = V2 i j+ where (j, i) = n `quotRem` x {-# INLINE shapeFromIndex #-} shapeStep (V2 x y) (V2 i j)- | j + 1 < y = Just (V2 i (j + 1))- | i + 1 < x = Just (V2 (i + 1) 0 )+ | i + 1 < x = Just (V2 (i + 1) j )+ | j + 1 < y = Just (V2 0 (j + 1)) | otherwise = Nothing {-# INLINE shapeStep #-} - unsafeShapeStep (V2 _ y) (V2 i j)- | j + 1 < y = V2 i (j + 1)- | otherwise = V2 (i + 1) 0+ unsafeShapeStep (V2 x _y) (V2 i j)+ | i + 1 < x = V2 (i + 1) j+ | otherwise = V2 0 (j + 1) {-# INLINE unsafeShapeStep #-} - shapeStepBetween (V2 _ia ja) (V2 ib jb) (V2 i j)- | j + 1 < jb = Just (V2 i (j + 1))- | i + 1 < ib = Just (V2 (i + 1) ja )+ shapeStepBetween (V2 ia _ja) (V2 ib jb) (V2 i j)+ | i + 1 < ib = Just (V2 (i + 1) j )+ | j + 1 < jb = Just (V2 ia (j + 1)) | otherwise = Nothing {-# INLINE shapeStepBetween #-} instance Shape V3 where+ shapeToIndex (V3 x y _z) (V3 i j k) = i + x*(j + y*k)+ {-# INLINE shapeToIndex #-}+ shapeStep (V3 x y z) (V3 i j k)- | k + 1 < z = Just (V3 i j (k + 1))- | j + 1 < y = Just (V3 i (j + 1) 0 )- | i + 1 < x = Just (V3 (i + 1) 0 0 )+ | k + 1 < z = Just (V3 (i + 1) j k )+ | j + 1 < y = Just (V3 0 (j + 1) k )+ | i + 1 < x = Just (V3 0 0 (k + 1)) | otherwise = Nothing {-# INLINE shapeStep #-} - shapeStepBetween (V3 _ia ja ka) (V3 ib jb kb) (V3 i j k)- | k < kb = Just (V3 i j (k + 1))- | j < jb = Just (V3 i (j + 1) ka )- | i < ib = Just (V3 (i + 1) ja ka )+ shapeStepBetween (V3 ia ja _ka) (V3 ib jb kb) (V3 i j k)+ | k < kb = Just (V3 (i + 1) j k )+ | j < jb = Just (V3 ia (j + 1) k )+ | i < ib = Just (V3 ia ja (k + 1)) | otherwise = Nothing {-# INLINE shapeStepBetween #-} instance Shape V4 where shapeStep (V4 x y z w) (V4 i j k l)- | l + 1 < w = Just (V4 i j k (l + 1))- | k + 1 < z = Just (V4 i j (k + 1) 0 )- | j + 1 < y = Just (V4 i (j + 1) 0 0 )- | i + 1 < x = Just (V4 (i + 1) 0 0 0 )+ | l + 1 < w = Just (V4 (i + 1) j k l )+ | k + 1 < z = Just (V4 0 (j + 1) k l )+ | j + 1 < y = Just (V4 0 0 (k + 1) l )+ | i + 1 < x = Just (V4 0 0 0 (l + 1)) | otherwise = Nothing {-# INLINE shapeStep #-} - shapeStepBetween (V4 _ia ja ka la) (V4 ib jb kb lb) (V4 i j k l)- | l < lb = Just (V4 i j k (l + 1))- | k < kb = Just (V4 i j (k + 1) la )- | j < jb = Just (V4 i (j + 1) ka la )- | i < ib = Just (V4 (i + 1) ja ka la )+ shapeStepBetween (V4 ia ja ka _la) (V4 ib jb kb lb) (V4 i j k l)+ | l < lb = Just (V4 (i + 1) j k l )+ | k < kb = Just (V4 ia (j + 1) k l )+ | j < jb = Just (V4 ia ja (k + 1) l )+ | i < ib = Just (V4 ia ia ka (l + 1)) | otherwise = Nothing {-# INLINE shapeStepBetween #-}
src/Data/Dense/Mutable.hs view
@@ -107,7 +107,7 @@ -- | Lens onto the shape of the vector. The total size of the layout -- _must_ remain the same or an error is thrown.-mlayout :: (Shape l, Shape l') => Lens (MArray v l s a) (MArray v l' s a) (Layout l) (Layout l')+mlayout :: (Shape f, Shape f') => Lens (MArray v f s a) (MArray v f' s a) (Layout f) (Layout f') mlayout f (MArray l v) = f l <&> \l' -> sizeMissmatch (F.product l) (F.product l') ("mlayout: trying to replace shape " ++ showShape l ++ ", with " ++ showShape l')@@ -121,7 +121,7 @@ -- | Indexed lens over the underlying vector of an array. The index is -- the 'extent' of the array. You must __not__ change the length of -- the vector, otherwise an error will be thrown.-mvector :: (MVector v a, MVector w b) => IndexedLens (Layout l) (MArray v l s a) (MArray w l t b) (v s a) (w t b)+mvector :: (MVector v a, MVector w b) => IndexedLens (Layout f) (MArray v f s a) (MArray w f t b) (v s a) (w t b) mvector f (MArray l v) = indexed f l v <&> \w -> sizeMissmatch (GM.length v) (GM.length w)@@ -130,23 +130,23 @@ {-# INLINE mvector #-} -- | New mutable array with shape @l@.-new :: (PrimMonad m, Shape l, MVector v a) => Layout l -> m (MArray v l (PrimState m) a)+new :: (PrimMonad m, Shape f, MVector v a) => Layout f -> m (MArray v f (PrimState m) a) new l = MArray l `liftM` GM.new (F.product l) {-# INLINE new #-} -- | New mutable array with shape @l@ filled with element @a@.-replicate :: (PrimMonad m, Shape l, MVector v a) => Layout l -> a -> m (MArray v l (PrimState m) a)+replicate :: (PrimMonad m, Shape f, MVector v a) => Layout f -> a -> m (MArray v f (PrimState m) a) replicate l a = MArray l `liftM` GM.replicate (F.product l) a {-# INLINE replicate #-} -- | New mutable array with shape @l@ filled with result of monadic -- action @a@.-replicateM :: (PrimMonad m, Shape l, MVector v a) => Layout l -> m a -> m (MArray v l (PrimState m) a)+replicateM :: (PrimMonad m, Shape f, MVector v a) => Layout f -> m a -> m (MArray v f (PrimState m) a) replicateM l a = MArray l `liftM` GM.replicateM (F.product l) a {-# INLINE replicateM #-} -- | Clone a mutable array, making a new, separate mutable array.-clone :: (PrimMonad m, MVector v a) => MArray v l (PrimState m) a -> m (MArray v l (PrimState m) a)+clone :: (PrimMonad m, MVector v a) => MArray v f (PrimState m) a -> m (MArray v f (PrimState m) a) clone (MArray l v) = MArray l `liftM` GM.clone v {-# INLINE clone #-} @@ -154,130 +154,130 @@ -- | Clear the elements of a mutable array. This is usually a no-op for -- unboxed arrays.-clear :: (PrimMonad m, MVector v a) => MArray v l (PrimState m) a -> m ()+clear :: (PrimMonad m, MVector v a) => MArray v f (PrimState m) a -> m () clear (MArray _ v) = GM.clear v {-# INLINE clear #-} -- | Read a mutable array at element @l@.-read :: (PrimMonad m, Shape l, MVector v a) => MArray v l (PrimState m) a -> l Int -> m a+read :: (PrimMonad m, Shape f, MVector v a) => MArray v f (PrimState m) a -> f Int -> m a read (MArray l v) s = boundsCheck l s $ GM.unsafeRead v (shapeToIndex l s) {-# INLINE read #-} -- | Write a mutable array at element @l@.-write :: (PrimMonad m, Shape l, MVector v a) => MArray v l (PrimState m) a -> l Int -> a -> m ()+write :: (PrimMonad m, Shape f, MVector v a) => MArray v f (PrimState m) a -> f Int -> a -> m () write (MArray l v) s a = boundsCheck l s $ GM.unsafeWrite v (shapeToIndex l s) a {-# INLINE write #-} -- | Modify a mutable array at element @l@ by applying a function.-modify :: (PrimMonad m, Shape l, MVector v a) => MArray v l (PrimState m) a -> l Int -> (a -> a) -> m ()+modify :: (PrimMonad m, Shape f, MVector v a) => MArray v f (PrimState m) a -> f Int -> (a -> a) -> m () modify (MArray l v) s f = boundsCheck l s $ GM.unsafeRead v i >>= GM.unsafeWrite v i . f where i = shapeToIndex l s {-# INLINE modify #-} -- | Swap two elements in a mutable array.-swap :: (PrimMonad m, Shape l, MVector v a) => MArray v l (PrimState m) a -> l Int -> l Int -> m ()+swap :: (PrimMonad m, Shape f, MVector v a) => MArray v f (PrimState m) a -> f Int -> f Int -> m () swap (MArray l v) i j = boundsCheck l i boundsCheck l j $ GM.unsafeSwap v (shapeToIndex l i) (shapeToIndex l j) {-# INLINE swap #-} -- | Replace the element at the give position and return the old -- element.-exchange :: (PrimMonad m, Shape l, MVector v a) => MArray v l (PrimState m) a -> l Int -> a -> m a+exchange :: (PrimMonad m, Shape f, MVector v a) => MArray v f (PrimState m) a -> f Int -> a -> m a exchange (MArray l v) i a = boundsCheck l i $ GM.unsafeExchange v (shapeToIndex l i) a {-# INLINE exchange #-} -- | Read a mutable array at element @i@ by indexing the internal -- vector.-linearRead :: (PrimMonad m, MVector v a) => MArray v l (PrimState m) a -> Int -> m a+linearRead :: (PrimMonad m, MVector v a) => MArray v f (PrimState m) a -> Int -> m a linearRead (MArray _ v) = GM.read v {-# INLINE linearRead #-} -- | Write a mutable array at element @i@ by indexing the internal -- vector.-linearWrite :: (PrimMonad m, MVector v a) => MArray v l (PrimState m) a -> Int -> a -> m ()+linearWrite :: (PrimMonad m, MVector v a) => MArray v f (PrimState m) a -> Int -> a -> m () linearWrite (MArray _ v) = GM.write v {-# INLINE linearWrite #-} -- | Swap two elements in a mutable array by indexing the internal -- vector.-linearSwap :: (PrimMonad m, MVector v a) => MArray v l (PrimState m) a -> Int -> Int -> m ()+linearSwap :: (PrimMonad m, MVector v a) => MArray v f (PrimState m) a -> Int -> Int -> m () linearSwap (MArray _ v) = GM.swap v {-# INLINE linearSwap #-} -- | Modify a mutable array at element @i@ by applying a function.-linearModify :: (PrimMonad m, MVector v a) => MArray v l (PrimState m) a -> Int -> (a -> a) -> m ()+linearModify :: (PrimMonad m, MVector v a) => MArray v f (PrimState m) a -> Int -> (a -> a) -> m () linearModify (MArray _ v) i f = GM.read v i >>= GM.unsafeWrite v i . f {-# INLINE linearModify #-} -- | Replace the element at the give position and return the old -- element.-linearExchange :: (PrimMonad m, MVector v a) => MArray v l (PrimState m) a -> Int -> a -> m a+linearExchange :: (PrimMonad m, MVector v a) => MArray v f (PrimState m) a -> Int -> a -> m a linearExchange (MArray _ v) i a = GM.exchange v i a {-# INLINE linearExchange #-} -- Unsafe varients -- | 'read' without bounds checking.-unsafeRead :: (PrimMonad m, Shape l, MVector v a) => MArray v l (PrimState m) a -> l Int -> m a+unsafeRead :: (PrimMonad m, Shape f, MVector v a) => MArray v f (PrimState m) a -> f Int -> m a unsafeRead (MArray l v) s = GM.unsafeRead v (shapeToIndex l s) {-# INLINE unsafeRead #-} -- | 'write' without bounds checking.-unsafeWrite :: (PrimMonad m, Shape l, MVector v a) => MArray v l (PrimState m) a -> l Int -> a -> m ()+unsafeWrite :: (PrimMonad m, Shape f, MVector v a) => MArray v f (PrimState m) a -> f Int -> a -> m () unsafeWrite (MArray l v) s = GM.unsafeWrite v (shapeToIndex l s) {-# INLINE unsafeWrite #-} -- | 'swap' without bounds checking.-unsafeSwap :: (PrimMonad m, Shape l, MVector v a) => MArray v l (PrimState m) a -> l Int -> l Int -> m ()+unsafeSwap :: (PrimMonad m, Shape f, MVector v a) => MArray v f (PrimState m) a -> f Int -> f Int -> m () unsafeSwap (MArray l v) s j = GM.unsafeSwap v (shapeToIndex l s) (shapeToIndex j s) {-# INLINE unsafeSwap #-} -- | 'modify' without bounds checking.-unsafeModify :: (PrimMonad m, Shape l, MVector v a) => MArray v l (PrimState m) a -> l Int -> (a -> a) -> m ()+unsafeModify :: (PrimMonad m, Shape f, MVector v a) => MArray v f (PrimState m) a -> f Int -> (a -> a) -> m () unsafeModify (MArray l v) s f = GM.unsafeRead v i >>= GM.unsafeWrite v i . f where i = shapeToIndex l s {-# INLINE unsafeModify #-} -- | Replace the element at the give position and return the old -- element.-unsafeExchange :: (PrimMonad m, Shape l, MVector v a) => MArray v l (PrimState m) a -> l Int -> a -> m a+unsafeExchange :: (PrimMonad m, Shape f, MVector v a) => MArray v f (PrimState m) a -> f Int -> a -> m a unsafeExchange (MArray l v) i a = GM.unsafeExchange v (shapeToIndex l i) a {-# INLINE unsafeExchange #-} -- | 'linearRead' without bounds checking.-unsafeLinearRead :: (PrimMonad m, MVector v a) => MArray v l (PrimState m) a -> Int -> m a+unsafeLinearRead :: (PrimMonad m, MVector v a) => MArray v f (PrimState m) a -> Int -> m a unsafeLinearRead (MArray _ v) = GM.unsafeRead v {-# INLINE unsafeLinearRead #-} -- | 'linearWrite' without bounds checking.-unsafeLinearWrite :: (PrimMonad m, MVector v a) => MArray v l (PrimState m) a -> Int -> a -> m ()+unsafeLinearWrite :: (PrimMonad m, MVector v a) => MArray v f (PrimState m) a -> Int -> a -> m () unsafeLinearWrite (MArray _ v) = GM.unsafeWrite v {-# INLINE unsafeLinearWrite #-} -- | 'linearSwap' without bounds checking.-unsafeLinearSwap :: (PrimMonad m, MVector v a) => MArray v l (PrimState m) a -> Int -> Int -> m ()+unsafeLinearSwap :: (PrimMonad m, MVector v a) => MArray v f (PrimState m) a -> Int -> Int -> m () unsafeLinearSwap (MArray _ v) = GM.unsafeSwap v {-# INLINE unsafeLinearSwap #-} -- | 'linearModify' without bounds checking.-unsafeLinearModify :: (PrimMonad m, MVector v a) => MArray v l (PrimState m) a -> Int -> (a -> a) -> m ()+unsafeLinearModify :: (PrimMonad m, MVector v a) => MArray v f (PrimState m) a -> Int -> (a -> a) -> m () unsafeLinearModify (MArray _ v) i f = GM.unsafeRead v i >>= GM.unsafeWrite v i . f {-# INLINE unsafeLinearModify #-} -- | Replace the element at the give position and return the old -- element.-unsafeLinearExchange :: (PrimMonad m, MVector v a) => MArray v l (PrimState m) a -> Int -> a -> m a+unsafeLinearExchange :: (PrimMonad m, MVector v a) => MArray v f (PrimState m) a -> Int -> a -> m a unsafeLinearExchange (MArray _ v) i a = GM.unsafeExchange v i a {-# INLINE unsafeLinearExchange #-} -- Filling and copying ------------------------------------------------- -- | Set all elements in a mutable array to a constant value.-set :: (PrimMonad m, MVector v a) => MArray v l (PrimState m) a -> a -> m ()+set :: (PrimMonad m, MVector v a) => MArray v f (PrimState m) a -> a -> m () set (MArray _ v) = GM.set v {-# INLINE set #-} -- | Copy all elements from one array into another.-copy :: (PrimMonad m, MVector v a) => MArray v l (PrimState m) a -> MArray v l (PrimState m) a -> m ()+copy :: (PrimMonad m, MVector v a) => MArray v f (PrimState m) a -> MArray v f (PrimState m) a -> m () copy (MArray _ v) (MArray _ u) = GM.copy v u {-# INLINE copy #-} @@ -286,7 +286,7 @@ -- Array v V1 a is essentially v a with a wrapper. Instance is provided -- for convience. -instance (MVector v a, l ~ V1) => MVector (MArray v l) a where+instance (MVector v a, f ~ V1) => MVector (MArray v f) a where {-# INLINE basicLength #-} {-# INLINE basicUnsafeSlice #-} {-# INLINE basicOverlaps #-}
src/Data/Dense/TH.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE LambdaCase #-}@@ -60,6 +61,13 @@ import Data.Dense.Index import Data.Dense.Stencil +tupe :: [Exp] -> Exp+#if __GLASGOW_HASKELL__ <= 808+tupe = TupE+#else+tupe = TupE . map Just+#endif+ -- | QuasiQuoter for producing a dense arrays using a custom parser. -- Values are space separated, while also allowing infix expressions -- (like @5/7@). If you want to apply a function, it should be done in@@ -500,7 +508,7 @@ -- parenthesis / tuples "(" -> do as <- expression `sepBy` comma Lex.Punc ")" <- Lex.lex- pure $ TupE as+ pure $ tupe as -- lists "[" -> do as <- expression `sepBy` comma Lex.Punc "]" <- Lex.lex@@ -593,8 +601,8 @@ | otherwise = do vN <- newName "v" let idx i = AppE (AppE (VarE 'Vector.unsafeIndex) (VarE vN)) (intE i)- let xs = TupE $ map idx [0..n-1]- a <- newName "a"+ let xs = tupe $ map idx [0..n-1]+ a <- newName "a" let tup = iterate (\x -> AppT x (VarT a)) (TupleT n) !! n typ = ForallT [PlainTV a] [] (AppT (AppT ArrowT (AppT (AppT (ConT ''V.V) (intT n)) (VarT a))) tup)