massiv 0.1.5.0 → 0.1.6.0
raw patch · 7 files changed
+122/−19 lines, 7 filesdep +semigroupsPVP ok
version bump matches the API change (PVP)
Dependencies added: semigroups
API changes (from Hackage documentation)
+ Data.Massiv.Array: foldSemi :: (Source r ix e, Semigroup m) => (e -> m) -> m -> Array r ix e -> m
+ Data.Massiv.Array.Unsafe: forStencilUnsafe :: (Source r ix e, Manifest r ix e) => Array r ix e -> ix -> ix -> ((ix -> Maybe e) -> a) -> Array DW ix a
Files
- massiv.cabal +5/−1
- src/Data/Massiv/Array/Ops/Fold.hs +17/−3
- src/Data/Massiv/Array/Stencil/Internal.hs +49/−3
- src/Data/Massiv/Array/Unsafe.hs +5/−0
- src/Data/Massiv/Core/Computation.hs +5/−6
- tests/Data/Massiv/Array/Ops/FoldSpec.hs +22/−1
- tests/Data/Massiv/CoreArbitrary.hs +19/−5
massiv.cabal view
@@ -1,5 +1,5 @@ name: massiv-version: 0.1.5.0+version: 0.1.6.0 synopsis: Massiv (Массив) is an Array Library. description: Multi-dimensional Arrays with fusion, stencils and parallel computation. homepage: https://github.com/lehins/massiv@@ -57,6 +57,10 @@ , ghc-prim , primitive , vector++ if impl(ghc < 8.0)+ build-depends: semigroups+ default-language: Haskell2010 ghc-options: -Wall
src/Data/Massiv/Array/Ops/Fold.hs view
@@ -18,6 +18,7 @@ fold , foldMono+ , foldSemi , minimum , maximum , sum@@ -71,7 +72,7 @@ import Data.Massiv.Array.Ops.Map (map) import Data.Massiv.Core import Data.Massiv.Core.Common-import Data.Monoid+import Data.Semigroup import Prelude hiding (all, and, any, foldl, foldr, map, maximum, minimum, or,@@ -85,10 +86,23 @@ => (e -> m) -- ^ Convert each element of an array to an appropriate `Monoid`. -> Array r ix e -- ^ Source array -> m-foldMono f = foldl (<>) mempty (<>) mempty . map f+foldMono f = foldl mappend mempty mappend mempty . map f {-# INLINE foldMono #-} +-- | /O(n)/ - Semigroup fold over an array.+--+-- @since 0.1.6+foldSemi ::+ (Source r ix e, Semigroup m)+ => (e -> m) -- ^ Convert each element of an array to an appropriate `Semigroup`.+ -> m -- ^ Initial element that must be neutral to the (`<>`) function.+ -> Array r ix e -- ^ Source array+ -> m+foldSemi f m = foldl (<>) m (<>) m . map f+{-# INLINE foldSemi #-}++ -- | /O(n)/ - Compute maximum of all elements. maximum :: (Source r ix e, Ord e) => Array r ix e -> e@@ -105,7 +119,7 @@ minimum = \arr -> if isEmpty arr then error "Data.Massiv.Array.minimum - empty"- else fold max (evaluateAt arr zeroIndex) arr+ else fold min (evaluateAt arr zeroIndex) arr {-# INLINE minimum #-}
src/Data/Massiv/Array/Stencil/Internal.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}@@ -16,9 +17,14 @@ import Control.Applicative import Control.DeepSeq-import Data.Massiv.Core.Common+import Data.Default.Class (Default (def)) import Data.Massiv.Array.Delayed.Internal-import Data.Default.Class (Default (def))+import Data.Massiv.Array.Delayed.Windowed+import Data.Massiv.Core.Common+import GHC.Exts (inline)+#if !MIN_VERSION_base(4,11,0)+import Data.Semigroup+#endif -- | Stencil is abstract description of how to handle elements in the neighborhood of every array -- cell in order to compute a value for the cells in the new array. Use `Data.Array.makeStencil` and@@ -38,7 +44,6 @@ -- it possible to manipulate the value, without having direct access to it. newtype Value e = Value { unValue :: e } deriving (Show, Eq, Ord, Bounded) - instance Functor Value where fmap f (Value e) = Value (f e) {-# INLINE fmap #-}@@ -49,6 +54,18 @@ (<*>) (Value f) (Value e) = Value (f e) {-# INLINE (<*>) #-} +-- | @since 0.1.5+instance Semigroup a => Semigroup (Value a) where+ Value a <> Value b = Value (a <> b)+ {-# INLINE (<>) #-}++-- | @since 0.1.5+instance Monoid a => Monoid (Value a) where+ mempty = Value mempty+ {-# INLINE mempty #-}+ Value a `mappend` Value b = Value (a `mappend` b)+ {-# INLINE mappend #-}+ instance Num e => Num (Value e) where (+) = liftA2 (+) {-# INLINE (+) #-}@@ -222,3 +239,32 @@ in stencil (Value . safeStencilIndex valArr) sCenter `seq` s {-# INLINE validateStencil #-} ++-- | This is an unsafe version of the stencil computation. There are no bounds check further from+-- the border, so if you make sure you don't go outside the size of the stencil, you will be safe,+-- but this is not enforced.+forStencilUnsafe ::+ (Source r ix e, Manifest r ix e)+ => Array r ix e+ -> ix -- ^ Size of the stencil+ -> ix -- ^ Center of the stencil+ -> ((ix -> Maybe e) -> a)+ -- ^ Stencil function that receives a "get" function as it's argument that can+ -- retrieve values of cells in the source array with respect to the center of+ -- the stencil. Stencil function must return a value that will be assigned to+ -- the cell in the result array. Offset supplied to the "get" function+ -- cannot go outside the boundaries of the stencil, otherwise an error will be+ -- raised during stencil creation.+ -> Array DW ix a+forStencilUnsafe !arr !sSz !sCenter relStencil =+ DWArray+ (DArray (getComp arr) sz (stencil (index arr)))+ (Just sSz)+ sCenter+ (liftIndex2 (-) sz (liftIndex2 (-) sSz (pureIndex 1)))+ (stencil (Just . unsafeIndex arr))+ where+ stencil getVal !ix = (inline relStencil $ \ !ixD -> getVal (liftIndex2 (+) ix ixD))+ {-# INLINE stencil #-}+ !sz = size arr+{-# INLINE forStencilUnsafe #-}
src/Data/Massiv/Array/Unsafe.hs view
@@ -39,11 +39,14 @@ , unsafeLinearRead , unsafeWrite , unsafeLinearWrite+ -- * Stencil+ , forStencilUnsafe ) where import Control.Monad.Primitive (PrimMonad (..)) import Control.Monad.ST (runST) import Data.Massiv.Array.Delayed.Internal (D)+import Data.Massiv.Array.Stencil.Internal import Data.Massiv.Core.Common import Data.Massiv.Core.Scheduler import System.IO.Unsafe (unsafePerformIO)@@ -103,6 +106,8 @@ -- | Create an array in parallel using mutable interface+--+-- @since 0.1.5 unsafeGenerateArrayP :: Mutable r ix e => [Int] -> ix -> (ix -> e) -> Array r ix e unsafeGenerateArrayP wIds !sz f = unsafePerformIO $ do marr <- unsafeNew sz
src/Data/Massiv/Core/Computation.hs view
@@ -15,16 +15,11 @@ ) where import Control.DeepSeq (NFData (..), deepseq)-#if MIN_VERSION_base(4,9,0) #if !MIN_VERSION_base(4,11,0)-import Data.Semigroup-#endif-instance Semigroup Comp where- (<>) = joinComp+import Data.Semigroup #endif - -- | Computation type to use. data Comp = Seq -- ^ Sequential computation@@ -58,6 +53,10 @@ {-# INLINE mempty #-} mappend = joinComp {-# INLINE mappend #-}++instance Semigroup Comp where+ (<>) = joinComp+ {-# INLINE (<>) #-} joinComp :: Comp -> Comp -> Comp
tests/Data/Massiv/Array/Ops/FoldSpec.hs view
@@ -4,11 +4,14 @@ {-# LANGUAGE MultiParamTypeClasses #-} module Data.Massiv.Array.Ops.FoldSpec (spec) where -import Data.Massiv.CoreArbitrary+import qualified Data.Foldable as F+import Data.Massiv.CoreArbitrary as A+import Data.Semigroup import Prelude hiding (map, product, sum) import qualified Prelude as P (length, sum) import Test.Hspec import Test.QuickCheck+import Test.QuickCheck.Function import Test.QuickCheck.Monadic @@ -55,6 +58,20 @@ it "sumS Eq sumP" $ property $ prop_SumSEqSumP proxy it "prodS Eq prodP" $ property $ prop_ProdSEqProdP proxy +foldOpsProp :: (Source P ix Int) => proxy ix -> Fun Int Bool -> ArrTiny1 P ix Int -> Property+foldOpsProp _ f (ArrTiny1 arr) =+ (A.maximum arr === getMax (foldMono Max arr)) .&&.+ (A.minimum arr === getMin (foldSemi Min maxBound arr)) .&&.+ (A.sum arr === F.sum ls) .&&.+ (A.product (A.map ((+ 0.1) . (fromIntegral :: Int -> Double)) arr) ===+ getProduct (foldMono (Product . (+ 0.1) . fromIntegral) arr)) .&&.+ (A.all (apply f) arr === F.all (apply f) ls) .&&.+ (A.any (apply f) arr === F.any (apply f) ls) .&&.+ (A.or (A.map (apply f) arr) === F.or (fmap (apply f) ls)) .&&.+ (A.and (A.map (apply f) arr) === F.and (fmap (apply f) ls))+ where+ ls = toList arr+ spec :: Spec spec = do specFold (Nothing :: Maybe Ix1) "Ix1"@@ -62,3 +79,7 @@ it "Nested Parallel Fold" $ property prop_NestedFoldP it "FoldrOnP" $ property $ prop_FoldrOnP it "FoldlOnP" $ property $ prop_FoldlOnP+ describe "Foldable Props" do+ it "Ix1" $ property $ foldOpsProp (Nothing :: Maybe Ix1)+ it "Ix2" $ property $ foldOpsProp (Nothing :: Maybe Ix2)+ it "Ix3" $ property $ foldOpsProp (Nothing :: Maybe Ix3)
tests/Data/Massiv/CoreArbitrary.hs view
@@ -7,8 +7,10 @@ module Data.Massiv.CoreArbitrary ( Arr(..) , ArrTiny(..)+ , ArrTiny1(..) , ArrIx(..) , ArrP(..)+ , ArrS(..) , ArrIxP(..) , Sz(..) , SzIx(..)@@ -23,21 +25,23 @@ import Control.DeepSeq (NFData, deepseq) import Control.Exception (Exception, SomeException, catch)---import Data.Massiv.Array.Ops.Construct import Data.Massiv.Array import Data.Massiv.Core.IndexSpec hiding (spec) import Data.Typeable import Test.QuickCheck import Test.QuickCheck.Monadic -data Arr r ix e = Arr (Array r ix e)+newtype Arr r ix e = Arr {unArr :: Array r ix e} -data ArrTiny r ix e = ArrTiny (Array r ix e)+newtype ArrTiny r ix e = ArrTiny {unArrTiny :: Array r ix e} -data ArrS r ix e = ArrS (Array r ix e)+-- | Tiny but non-empty+newtype ArrTiny1 r ix e = ArrTiny1 {unArrTiny1 :: Array r ix e} -data ArrP r ix e = ArrP (Array r ix e)+newtype ArrS r ix e = ArrS {unArrS :: Array r ix e} +newtype ArrP r ix e = ArrP {unArrP :: Array r ix e}+ data ArrIx r ix e = ArrIx (Array r ix e) ix data ArrIxS r ix e = ArrIxS (Array r ix e) ix@@ -46,6 +50,7 @@ deriving instance (Show (Array r ix e)) => Show (Arr r ix e) deriving instance (Show (Array r ix e)) => Show (ArrTiny r ix e)+deriving instance (Show (Array r ix e)) => Show (ArrTiny1 r ix e) deriving instance (Show (Array r ix e)) => Show (ArrS r ix e) deriving instance (Show (Array r ix e)) => Show (ArrP r ix e) deriving instance (Show (Array r ix e), Show ix) => Show (ArrIx r ix e)@@ -74,6 +79,15 @@ func <- arbitrary comp <- oneof [pure Seq, pure Par] return $ ArrTiny $ makeArray comp (liftIndex (`mod` 10) sz) func++-- | Arbitrary small and possibly empty array. Computation strategy can be either `Seq` or `Par`.+instance (CoArbitrary ix, Arbitrary ix, Typeable e, Construct r ix e, Arbitrary e) =>+ Arbitrary (ArrTiny1 r ix e) where+ arbitrary = do+ SzZ sz <- arbitrary+ func <- arbitrary+ comp <- oneof [pure Seq, pure Par]+ return $ ArrTiny1 $ makeArray comp (liftIndex (succ . (`mod` 10)) sz) func -- | Arbitrary non-empty array. Computation strategy can be either `Seq` or `Par`. instance (CoArbitrary ix, Arbitrary ix, Typeable e, Construct r ix e, Arbitrary e) =>