massiv 0.1.4.0 → 0.1.5.0
raw patch · 4 files changed
+83/−8 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.Massiv.Array.Stencil: makeCorrelationStencil :: (Index ix, Num e) => Border e -> ix -> ix -> ((ix -> Value e -> Value e -> Value e) -> Value e -> Value e) -> Stencil ix e e
+ Data.Massiv.Array.Stencil: makeCorrelationStencilFromKernel :: (Manifest r ix e, Num e) => Border e -> Array r ix e -> Stencil ix e e
Files
- massiv.cabal +1/−1
- src/Data/Massiv/Array/Stencil.hs +5/−4
- src/Data/Massiv/Array/Stencil/Convolution.hs +46/−1
- tests/Data/Massiv/Array/StencilSpec.hs +31/−2
massiv.cabal view
@@ -1,5 +1,5 @@ name: massiv-version: 0.1.4.0+version: 0.1.5.0 synopsis: Massiv (Массив) is an Array Library. description: Multi-dimensional Arrays with fusion, stencils and parallel computation. homepage: https://github.com/lehins/massiv
src/Data/Massiv/Array/Stencil.hs view
@@ -10,12 +10,13 @@ -- Portability : non-portable -- module Data.Massiv.Array.Stencil- ( Stencil+ ( -- * Stencil+ Stencil , Value , mapStencil , makeStencil- , makeConvolutionStencil- , makeConvolutionStencilFromKernel+ -- * Convolution+ , module Data.Massiv.Array.Stencil.Convolution ) where import Data.Default.Class (Default (def))@@ -80,7 +81,7 @@ validateStencil def $ Stencil b sSz sCenter stencil where stencil getVal !ix =- (inline relStencil $ \ !ixD -> getVal (liftIndex2 (-) ix ixD))+ (inline relStencil $ \ !ixD -> getVal (liftIndex2 (+) ix ixD)) {-# INLINE stencil #-} {-# INLINE makeStencil #-}
src/Data/Massiv/Array/Stencil/Convolution.hs view
@@ -8,7 +8,12 @@ -- Stability : experimental -- Portability : non-portable ---module Data.Massiv.Array.Stencil.Convolution where+module Data.Massiv.Array.Stencil.Convolution+ ( makeConvolutionStencil+ , makeConvolutionStencilFromKernel+ , makeCorrelationStencil+ , makeCorrelationStencilFromKernel+ ) where import Data.Massiv.Core.Common import Data.Massiv.Array.Ops.Fold (ifoldlS)@@ -65,3 +70,43 @@ {-# INLINE accum #-} {-# INLINE stencil #-} {-# INLINE makeConvolutionStencilFromKernel #-}++++-- | Make a <https://en.wikipedia.org/wiki/Cross-correlation cross-correlation> stencil.+makeCorrelationStencil+ :: (Index ix, Num e)+ => Border e+ -> ix+ -> ix+ -> ((ix -> Value e -> Value e -> Value e) -> Value e -> Value e)+ -> Stencil ix e e+makeCorrelationStencil b !sSz !sCenter relStencil =+ validateStencil 0 $ Stencil b sSz sCenter stencil+ where+ stencil getVal !ix =+ ((inline relStencil $ \ !ixD !kVal !acc ->+ (getVal (liftIndex2 (+) ix ixD)) * kVal + acc)+ 0)+ {-# INLINE stencil #-}+{-# INLINE makeCorrelationStencil #-}+++-- | Make a stencil out of a Kernel Array. This `Stencil` will be slower than if+-- `makeCorrelationStencil` is used, but sometimes we just really don't know the+-- kernel at compile time.+makeCorrelationStencilFromKernel+ :: (Manifest r ix e, Num e)+ => Border e+ -> Array r ix e+ -> Stencil ix e e+makeCorrelationStencilFromKernel b kArr = Stencil b sz sCenter stencil+ where+ !sz = size kArr+ !sCenter = (liftIndex (`div` 2) sz)+ stencil getVal !ix = Value (ifoldlS accum 0 kArr) where+ accum !acc !kIx !kVal =+ unValue (getVal (liftIndex2 (+) ix (liftIndex2 (+) sCenter kIx))) * kVal + acc+ {-# INLINE accum #-}+ {-# INLINE stencil #-}+{-# INLINE makeCorrelationStencilFromKernel #-}
tests/Data/Massiv/Array/StencilSpec.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MonoLocalBinds #-}+{-# LANGUAGE OverloadedLists #-} {-# LANGUAGE MultiParamTypeClasses #-} module Data.Massiv.Array.StencilSpec (spec) where @@ -12,7 +13,7 @@ import Test.Hspec import Test.QuickCheck import Test.QuickCheck.Function-import Data.Default ()+import Data.Default (Default(def)) -- sum3x3Stencil :: (Default a, Fractional a) => Border a -> Stencil Ix2 a a -- sum3x3Stencil b = mkConvolutionStencil b (3 :. 3) (1 :. 1) $ \ get -> -- get (-1 :. -1) 1 . get (-1 :. 0) 1 . get (-1 :. 1) 1 .@@ -44,6 +45,7 @@ setIndex zeroIndex r i + stencilSpec :: Spec stencilSpec = do describe "MapSingletonStencil" $ do@@ -70,6 +72,33 @@ -- it "Ix3" $ property $ prop_toFromVector (Nothing :: Maybe Ix3) B +stencilDirection :: (Default a, Unbox a, Manifest r Ix2 a) => Ix2 -> Array r Ix2 a -> Array U Ix2 a+stencilDirection ix = computeAs U . mapStencil (makeStencil (Fill def) (3 :. 3) (1 :. 1) $ \f -> f ix) ++stencilCorners ::+ (Default a, Unbox a, Manifest r Ix2 a) => Ix2 -> Ix2 -> Array r Ix2 a -> Array U Ix2 a+stencilCorners ixC ix = computeAs U . mapStencil (makeStencil (Fill def) (3 :. 3) ixC $ \f -> f ix)+ spec :: Spec-spec = describe "Stencil" stencilSpec+spec = do+ describe "Stencil" $ do+ stencilSpec+ describe "Unit tests Ix2" $ do+ let arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] :: Array U Ix2 Int+ it "Direction Left" $+ stencilDirection (0 :. 1) arr `shouldBe` [[2, 3, 0], [5, 6, 0], [8, 9, 0]]+ it "Direction Right" $+ stencilDirection (0 :. -1) arr `shouldBe` [[0, 1, 2], [0, 4, 5], [0, 7, 8]]+ it "Direction Down" $+ stencilDirection (1 :. 0) arr `shouldBe` [[4, 5, 6], [7, 8, 9], [0, 0, 0]]+ it "Direction Up" $+ stencilDirection (-1 :. 0) arr `shouldBe` [[0, 0, 0], [1, 2, 3], [4, 5, 6]]+ it "Direction Left/Top Corner" $+ stencilCorners (0 :. 0) (2 :. 2) arr `shouldBe` [[9, 0, 0], [0, 0, 0], [0, 0, 0]]+ it "Direction Right/Top Corner" $+ stencilCorners (0 :. 2) (2 :. -2) arr `shouldBe` [[0, 0, 7], [0, 0, 0], [0, 0, 0]]+ it "Direction Right/Bottom Corner" $+ stencilCorners (2 :. 2) (-2 :. -2) arr `shouldBe` [[0, 0, 0], [0, 0, 0], [0, 0, 1]]+ it "Direction Left/Bottom Corner" $+ stencilCorners (2 :. 0) (-2 :. 2) arr `shouldBe` [[0, 0, 0], [0, 0, 0], [3, 0, 0]]