packages feed

massiv 0.5.3.2 → 0.5.4.0

raw patch · 17 files changed

+773/−229 lines, 17 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ Data.Massiv.Array: computeP :: forall r ix e r'. (Mutable r ix e, Construct r' ix e, Load r' ix e) => Array r' ix e -> Array r ix e
+ Data.Massiv.Array: innerSlices :: InnerSlice r ix e => Array r ix e -> Array D Ix1 (Elt r ix e)
+ Data.Massiv.Array: izipWith4 :: (Source r1 ix e1, Source r2 ix e2, Source r3 ix e3, Source r4 ix e4) => (ix -> e1 -> e2 -> e3 -> e4 -> e) -> Array r1 ix e1 -> Array r2 ix e2 -> Array r3 ix e3 -> Array r4 ix e4 -> Array D ix e
+ Data.Massiv.Array: outerSlices :: OuterSlice r ix e => Array r ix e -> Array D Ix1 (Elt r ix e)
+ Data.Massiv.Array: stackInnerSlicesM :: forall r ix e f m. (Foldable f, MonadThrow m, Source r (Lower ix) e, Index ix) => f (Array r (Lower ix) e) -> m (Array DL ix e)
+ Data.Massiv.Array: stackOuterSlicesM :: forall r ix e f m. (Foldable f, MonadThrow m, Source r (Lower ix) e, Index ix) => f (Array r (Lower ix) e) -> m (Array DL ix e)
+ Data.Massiv.Array: stackSlicesM :: forall r ix e f m. (Foldable f, MonadThrow m, Source r (Lower ix) e, Index ix) => Dim -> f (Array r (Lower ix) e) -> m (Array DL ix e)
+ Data.Massiv.Array: unzip4 :: Source r ix (e1, e2, e3, e4) => Array r ix (e1, e2, e3, e4) -> (Array D ix e1, Array D ix e2, Array D ix e3, Array D ix e4)
+ Data.Massiv.Array: withinSlices :: (IsIndexDimension ix n, Slice r ix e) => Dimension n -> Array r ix e -> Array D Ix1 (Elt r ix e)
+ Data.Massiv.Array: withinSlicesM :: (MonadThrow m, Slice r ix e) => Dim -> Array r ix e -> m (Array D Ix1 (Elt r ix e))
+ Data.Massiv.Array: zip4 :: (Source r1 ix e1, Source r2 ix e2, Source r3 ix e3, Source r4 ix e4) => Array r1 ix e1 -> Array r2 ix e2 -> Array r3 ix e3 -> Array r4 ix e4 -> Array D ix (e1, e2, e3, e4)
+ Data.Massiv.Array: zipWith4 :: (Source r1 ix e1, Source r2 ix e2, Source r3 ix e3, Source r4 ix e4) => (e1 -> e2 -> e3 -> e4 -> e) -> Array r1 ix e1 -> Array r2 ix e2 -> Array r3 ix e3 -> Array r4 ix e4 -> Array D ix e
+ Data.Massiv.Array.Unsafe: unsafeTransformStencil :: (Sz ix' -> Sz ix) -> (ix' -> ix) -> (((ix' -> Value e) -> ix' -> Value a) -> (ix -> Value e) -> ix -> Value a) -> Stencil ix' e a -> Stencil ix e a
- Data.Massiv.Array: appendM :: (MonadThrow m, Source r1 ix e, Source r2 ix e) => Dim -> Array r1 ix e -> Array r2 ix e -> m (Array DL ix e)
+ Data.Massiv.Array: appendM :: forall r1 r2 ix e m. (MonadThrow m, Source r1 ix e, Source r2 ix e) => Dim -> Array r1 ix e -> Array r2 ix e -> m (Array DL ix e)
- Data.Massiv.Array: concatM :: (MonadThrow m, Foldable f, Source r ix e) => Dim -> f (Array r ix e) -> m (Array DL ix e)
+ Data.Massiv.Array: concatM :: forall r ix e f m. (MonadThrow m, Foldable f, Source r ix e) => Dim -> f (Array r ix e) -> m (Array DL ix e)
- Data.Massiv.Array: downsample :: Source r ix e => Stride ix -> Array r ix e -> Array DL ix e
+ Data.Massiv.Array: downsample :: forall r ix e. Source r ix e => Stride ix -> Array r ix e -> Array DL ix e
- Data.Massiv.Array: iunfoldlS_ :: Construct DL ix e => Sz ix -> (ix -> a -> (a, e)) -> a -> Array DL ix e
+ Data.Massiv.Array: iunfoldlS_ :: forall ix e a. Construct DL ix e => Sz ix -> (ix -> a -> (a, e)) -> a -> Array DL ix e
- Data.Massiv.Array: iunfoldrS_ :: Construct DL ix e => Sz ix -> (a -> ix -> (e, a)) -> a -> Array DL ix e
+ Data.Massiv.Array: iunfoldrS_ :: forall ix e a. Construct DL ix e => Sz ix -> (a -> ix -> (e, a)) -> a -> Array DL ix e
- Data.Massiv.Array: upsample :: Load r ix e => e -> Stride ix -> Array r ix e -> Array DL ix e
+ Data.Massiv.Array: upsample :: forall r ix e. Load r ix e => e -> Stride ix -> Array r ix e -> Array DL ix e
- Data.Massiv.Array: zoom :: Source r ix e => Stride ix -> Array r ix e -> Array DL ix e
+ Data.Massiv.Array: zoom :: forall r ix e. Source r ix e => Stride ix -> Array r ix e -> Array DL ix e
- Data.Massiv.Array: zoomWithGrid :: Source r ix e => e -> Stride ix -> Array r ix e -> Array DL ix e
+ Data.Massiv.Array: zoomWithGrid :: forall r ix e. Source r ix e => e -> Stride ix -> Array r ix e -> Array DL ix e
- Data.Massiv.Array.Delayed: fromStrideLoad :: StrideLoad r ix e => Stride ix -> Array r ix e -> Array DL ix e
+ Data.Massiv.Array.Delayed: fromStrideLoad :: forall r ix e. StrideLoad r ix e => Stride ix -> Array r ix e -> Array DL ix e
- Data.Massiv.Array.Delayed: makeLoadArray :: Index ix => Comp -> Sz ix -> e -> (forall m. Monad m => Scheduler m () -> (ix -> e -> m Bool) -> m ()) -> Array DL ix e
+ Data.Massiv.Array.Delayed: makeLoadArray :: forall ix e. Index ix => Comp -> Sz ix -> e -> (forall m. Monad m => Scheduler m () -> (ix -> e -> m Bool) -> m ()) -> Array DL ix e
- Data.Massiv.Array.Delayed: makeLoadArrayS :: Index ix => Sz ix -> e -> (forall m. Monad m => (ix -> e -> m Bool) -> m ()) -> Array DL ix e
+ Data.Massiv.Array.Delayed: makeLoadArrayS :: forall ix e. Index ix => Sz ix -> e -> (forall m. Monad m => (ix -> e -> m Bool) -> m ()) -> Array DL ix e
- Data.Massiv.Array.Delayed: toLoadArray :: Load r ix e => Array r ix e -> Array DL ix e
+ Data.Massiv.Array.Delayed: toLoadArray :: forall r ix e. Load r ix e => Array r ix e -> Array DL ix e
- Data.Massiv.Array.Manifest: class (Load r ix e, Source r ix e) => Manifest r ix e
+ Data.Massiv.Array.Manifest: class Source r ix e => Manifest r ix e
- Data.Massiv.Array.Unsafe: unsafeMakeLoadArrayAdjusted :: Comp -> Sz ix -> Maybe e -> (forall m. Monad m => Scheduler m () -> (Int -> e -> m ()) -> m ()) -> Array DL ix e
+ Data.Massiv.Array.Unsafe: unsafeMakeLoadArrayAdjusted :: forall ix e. Comp -> Sz ix -> Maybe e -> (forall m. Monad m => Scheduler m () -> (Int -> e -> m ()) -> m ()) -> Array DL ix e
- Data.Massiv.Core: class (Load r ix e, Source r ix e) => Manifest r ix e
+ Data.Massiv.Core: class Source r ix e => Manifest r ix e
- Data.Massiv.Core: class Load r ix e => Source r ix e
+ Data.Massiv.Core: class (Resize r ix, Load r ix e) => Source r ix e

Files

CHANGELOG.md view
@@ -1,3 +1,14 @@+# 0.5.4++* Addition of `unsafeTransformStencil`+* Add `zip4`, `unzip4`, `zipWith4`  and `izipWith4`+* Make `Resize` a superclass of `Source`+* Addition of `outerSlices`, `innerSlices`, `withinSlices` and `withinSlicesM`+* Addition of `stackSlicesM`, `stackOuterSlicesM` and `stackInnerSlicesM`+* Addition of `computeP`+* Fix perfomrmance issue of folding functions applied to arrays with `Seq` computation+  strategy.+ # 0.5.3  * Fix `tanA` and `tanhA`. [#96](https://github.com/lehins/massiv/pull/96)
massiv.cabal view
@@ -1,5 +1,5 @@ name:                massiv-version:             0.5.3.2+version:             0.5.4.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.hs view
@@ -85,6 +85,7 @@   , setComp   , compute   , computeS+  , computeP   , computeIO   , computePrimM   , computeAs@@ -167,7 +168,6 @@ import Prelude as P hiding (all, and, any, enumFromTo, foldl, foldr, mapM,                             mapM_, maximum, minimum, or, product, replicate, splitAt,                             sum, zip)-  {- $folding 
src/Data/Massiv/Array/Delayed/Pull.hs view
@@ -110,6 +110,8 @@ instance Functor (Array D ix) where   fmap f (DArray c sz g) = DArray c sz (f . g)   {-# INLINE fmap #-}+  (<$) e (DArray c sz _) = DArray c sz (const e)+  {-# INLINE (<$) #-}   instance Index ix => Applicative (Array D ix) where@@ -148,8 +150,7 @@   {-# INLINE size #-}   getComp = dComp   {-# INLINE getComp #-}-  loadArrayM !scheduler !arr =-    splitLinearlyWith_ scheduler (elemsCount arr) (unsafeLinearIndex arr)+  loadArrayM !scheduler !arr = splitLinearlyWith_ scheduler (elemsCount arr) (unsafeLinearIndex arr)   {-# INLINE loadArrayM #-}  instance Index ix => StrideLoad D ix e
src/Data/Massiv/Array/Delayed/Push.hs view
@@ -56,9 +56,12 @@ instance Index ix => Construct DL ix e where   setComp c arr = arr {dlComp = c}   {-# INLINE setComp #-}-  makeArrayLinear comp sz f =-    DLArray comp sz Nothing $ \scheduler startAt dlWrite ->-      splitLinearlyWithStartAtM_ scheduler startAt (totalElem sz) (pure . f) dlWrite+  makeArrayLinear comp sz f = DLArray comp sz Nothing load+    where+      load :: Monad m => Scheduler m () -> Int -> (Int -> e -> m ()) -> m ()+      load scheduler startAt dlWrite =+        splitLinearlyWithStartAtM_ scheduler startAt (totalElem sz) (pure . f) dlWrite+      {-# INLINE load #-}   {-# INLINE makeArrayLinear #-}  instance Index ix => Resize DL ix where@@ -171,21 +174,25 @@ -- -- @since 0.3.1 makeLoadArrayS ::-     Index ix =>-     Sz ix+     forall ix e. Index ix+  => Sz ix   -- ^ Size of the resulting array   -> e   -- ^ Default value to use for all cells that might have been ommitted by the writing function-  -> (forall m. Monad m => (ix -> e -> m Bool) -> m ())+  -> (forall m. Monad m =>+                  (ix -> e -> m Bool) -> m ())   -- ^ Writing function that described which elements to write into the target array.   -> Array DL ix e-makeLoadArrayS sz defVal writer =-  DLArray Seq sz (Just defVal) $ \_scheduler !startAt uWrite ->-    let safeWrite !ix !e-          | isSafeIndex sz ix = uWrite (startAt + toLinearIndex sz ix) e >> pure True-          | otherwise = pure False-        {-# INLINE safeWrite #-}-     in writer safeWrite+makeLoadArrayS sz defVal writer = DLArray Seq sz (Just defVal) load+  where+    load :: Monad m => Scheduler m () -> Int -> (Int -> e -> m ()) -> m ()+    load _scheduler !startAt uWrite =+      let safeWrite !ix !e+            | isSafeIndex sz ix = uWrite (startAt + toLinearIndex sz ix) e >> pure True+            | otherwise = pure False+          {-# INLINE safeWrite #-}+       in writer safeWrite+    {-# INLINE load #-} {-# INLINE makeLoadArrayS #-}  -- | Specify how an array should be loaded into memory. Unlike `makeLoadArrayS`, loading@@ -194,7 +201,7 @@ -- -- @since 0.4.0 makeLoadArray ::-     Index ix+     forall ix e. Index ix   => Comp   -- ^ Computation strategy to use. Directly affects the scheduler that gets created for   -- the loading function.@@ -208,13 +215,16 @@   -- accepts a scheduler, that can be used for parallelization, as well as a safe element   -- writing function.   -> Array DL ix e-makeLoadArray comp sz defVal writer =-  DLArray comp sz (Just defVal) $ \scheduler !startAt uWrite ->-    let safeWrite !ix !e-          | isSafeIndex sz ix = uWrite (startAt + toLinearIndex sz ix) e >> pure True-          | otherwise = pure False-        {-# INLINE safeWrite #-}-     in writer scheduler safeWrite+makeLoadArray comp sz defVal writer = DLArray comp sz (Just defVal) load+  where+    load :: Monad m => Scheduler m () -> Int -> (Int -> e -> m ()) -> m ()+    load scheduler !startAt uWrite =+      let safeWrite !ix !e+            | isSafeIndex sz ix = uWrite (startAt + toLinearIndex sz ix) e >> pure True+            | otherwise = pure False+          {-# INLINE safeWrite #-}+       in writer scheduler safeWrite+    {-# INLINE load #-} {-# INLINE makeLoadArray #-}  -- | Specify how an array can be loaded/computed through creation of a `DL` array. Unlike@@ -250,36 +260,51 @@ -- -- @since 0.5.2 unsafeMakeLoadArrayAdjusted ::+     forall ix e.      Comp   -> Sz ix   -> Maybe e-  -> (forall m. Monad m => Scheduler m () -> (Int -> e -> m ()) -> m ())+  -> (forall m. Monad m =>+                  Scheduler m () -> (Int -> e -> m ()) -> m ())   -> Array DL ix e-unsafeMakeLoadArrayAdjusted comp sz mDefVal writer =-  DLArray comp sz mDefVal $ \scheduler !startAt uWrite ->-    writer scheduler (\i -> uWrite (startAt + i))+unsafeMakeLoadArrayAdjusted comp sz mDefVal writer = DLArray comp sz mDefVal load+  where+    load :: Monad m => Scheduler m () -> Int -> (Int -> e -> m ()) -> m ()+    load scheduler !startAt uWrite = writer scheduler (\i -> uWrite (startAt + i))+    {-# INLINE load #-} {-# INLINE unsafeMakeLoadArrayAdjusted #-}  -- | Convert any `Load`able array into `DL` representation. -- -- @since 0.3.0-toLoadArray :: Load r ix e => Array r ix e -> Array DL ix e-toLoadArray arr =-  DLArray (getComp arr) (size arr) Nothing $ \scheduler startAt dlWrite ->-    loadArrayM scheduler arr (dlWrite . (+ startAt))+toLoadArray ::+     forall r ix e. Load r ix e+  => Array r ix e+  -> Array DL ix e+toLoadArray arr = DLArray (getComp arr) (size arr) (defaultElement arr) load+  where+    load :: Monad m => Scheduler m () -> Int -> (Int -> e -> m ()) -> m ()+    load scheduler !startAt dlWrite = loadArrayM scheduler arr (dlWrite . (+ startAt))+    {-# INLINE load #-} {-# INLINE[1] toLoadArray #-} {-# RULES "toLoadArray/id" toLoadArray = id #-}  -- | Convert an array that can be loaded with stride into `DL` representation. -- -- @since 0.3.0-fromStrideLoad-  :: StrideLoad r ix e => Stride ix -> Array r ix e -> Array DL ix e+fromStrideLoad ::+     forall r ix e. StrideLoad r ix e+  => Stride ix+  -> Array r ix e+  -> Array DL ix e fromStrideLoad stride arr =-  DLArray (getComp arr) newsz Nothing $ \scheduler startAt dlWrite ->-    loadArrayWithStrideM scheduler stride newsz arr (\ !i -> dlWrite (i + startAt))+  DLArray (getComp arr) newsz Nothing load   where     newsz = strideSize stride (size arr)+    load :: Monad m => Scheduler m () -> Int -> (Int -> e -> m ()) -> m ()+    load scheduler !startAt dlWrite =+      loadArrayWithStrideM scheduler stride newsz arr (\ !i -> dlWrite (i + startAt))+    {-# INLINE load #-} {-# INLINE fromStrideLoad #-}  instance Index ix => Load DL ix e where@@ -293,10 +318,12 @@   {-# INLINE defaultElement #-}  instance Functor (Array DL ix) where-  fmap f arr =-    arr-      { dlLoad =-          \scheduler startAt uWrite -> dlLoad arr scheduler startAt (\ !i e -> uWrite i (f e))-      , dlDefault = f <$> dlDefault arr-      }+  fmap f arr = arr {dlLoad = loadFunctor arr f, dlDefault = f <$> dlDefault arr}   {-# INLINE fmap #-}+  (<$) e arr = arr {dlLoad = \_ _ _ -> pure (), dlDefault = Just e}+  {-# INLINE (<$) #-}++loadFunctor ::+     Monad m => Array DL ix t1 -> (t1 -> t2) -> Scheduler m () -> Int -> (Int -> t2 -> m ()) -> m ()+loadFunctor arr f scheduler startAt uWrite = dlLoad arr scheduler startAt (\ !i e -> uWrite i (f e))+{-# INLINE loadFunctor #-}
src/Data/Massiv/Array/Manifest/Internal.hs view
@@ -23,6 +23,7 @@   , toManifest   , compute   , computeS+  , computeP   , computeIO   , computePrimM   , computeAs@@ -221,6 +222,19 @@ computeS :: forall r ix e r' . (Mutable r ix e, Load r' ix e) => Array r' ix e -> Array r ix e computeS !arr = runST $ computePrimM arr {-# INLINE computeS #-}+++-- | Compute array in parallel using all cores disregarding predefined computation+-- strategy. Computation stategy of the resulting array will match the source, despite+-- that it is diregarded.+--+-- @since 0.5.4+computeP ::+     forall r ix e r'. (Mutable r ix e, Construct r' ix e, Load r' ix e)+  => Array r' ix e+  -> Array r ix e+computeP arr = setComp (getComp arr) $ compute (setComp Par arr)+{-# INLINE computeP #-}  -- | Very similar to `compute`, but computes an array inside the `IO` monad. Despite being -- deterministic and referentially transparent, because this is an `IO` action it
src/Data/Massiv/Array/Mutable.hs view
@@ -418,7 +418,6 @@ --   [ 10, 12 ] -- -- @since 0.3.0--- createArrayS_ ::      forall r ix e a m. (Mutable r ix e, PrimMonad m)   => Sz ix -- ^ Size of the newly created array@@ -431,7 +430,6 @@ -- | Just like `createArray_`, but together with `Array` it returns the result of the filling action. -- -- @since 0.3.0--- createArrayS ::      forall r ix e a m. (Mutable r ix e, PrimMonad m)   => Sz ix -- ^ Size of the newly created array@@ -448,7 +446,6 @@ -- | Just like `createArrayS_`, but restricted to `ST`. -- -- @since 0.3.0--- createArrayST_ ::      forall r ix e a. Mutable r ix e   => Sz ix@@ -461,7 +458,6 @@ -- | Just like `createArrayS`, but restricted to `ST`. -- -- @since 0.2.6--- createArrayST ::      forall r ix e a. Mutable r ix e   => Sz ix@@ -477,8 +473,6 @@ -- but is a stateful action, becuase it is restricted to `PrimMonad` thus allows for sharing -- the state between computation of each element. ----- @since 0.2.6--- -- ====__Examples__ -- -- >>> import Data.Massiv.Array@@ -496,6 +490,7 @@ -- >>> readIORef ref -- 15 --+-- @since 0.2.6 generateArrayS ::      forall r ix e m. (Mutable r ix e, PrimMonad m)   => Sz ix -- ^ Resulting size of the array@@ -603,7 +598,6 @@ --   [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ] -- -- @since 0.3.0--- unfoldrPrimM_ ::      forall r ix e a m. (Mutable r ix e, PrimMonad m)   => Sz ix -- ^ Size of the desired array@@ -616,7 +610,6 @@ -- | Same as `unfoldrPrimM_` but do the unfolding with index aware function. -- -- @since 0.3.0--- iunfoldrPrimM_ ::      forall r ix e a m. (Mutable r ix e, PrimMonad m)   => Sz ix -- ^ Size of the desired array@@ -686,7 +679,6 @@ --   [ 34, 21, 13, 8, 5, 3, 2, 1, 1, 0 ] -- -- @since 0.3.0--- unfoldlPrimM_ ::      forall r ix e a m. (Mutable r ix e, PrimMonad m)   => Sz ix -- ^ Size of the desired array@@ -699,7 +691,6 @@ -- | Same as `unfoldlPrimM_` but do the unfolding with index aware function. -- -- @since 0.3.0--- iunfoldlPrimM_ ::      forall r ix e a m. (Mutable r ix e, PrimMonad m)   => Sz ix -- ^ Size of the desired array
src/Data/Massiv/Array/Ops/Construct.hs view
@@ -225,21 +225,21 @@ -- | Right unfold of a delayed load array with index aware function -- -- @since 0.3.0-iunfoldrS_-  :: Construct DL ix e => Sz ix -> (a -> ix -> (e, a)) -> a -> Array DL ix e-iunfoldrS_ sz f acc0 =-  DLArray-    { dlComp = Seq-    , dlSize = sz-    , dlDefault = Nothing-    , dlLoad =-        \_ startAt dlWrite ->-          void $-          loopM startAt (< (totalElem sz + startAt)) (+ 1) acc0 $ \ !i !acc -> do-            let (e, acc') = f acc $ fromLinearIndex sz (i - startAt)-            dlWrite i e-            pure acc'-    }+iunfoldrS_ ::+     forall ix e a. Construct DL ix e+  => Sz ix+  -> (a -> ix -> (e, a))+  -> a+  -> Array DL ix e+iunfoldrS_ sz f acc0 = DLArray {dlComp = Seq, dlSize = sz, dlDefault = Nothing, dlLoad = load}+  where+    load :: Monad m => Scheduler m () -> Int -> (Int -> e -> m ()) -> m ()+    load _ startAt dlWrite =+      void $+      loopM startAt (< (totalElem sz + startAt)) (+ 1) acc0 $ \ !i !acc ->+        let (e, acc') = f acc $ fromLinearIndex sz (i - startAt)+         in acc' <$ dlWrite i e+    {-# INLINE load #-} {-# INLINE iunfoldrS_ #-}  @@ -255,20 +255,21 @@ -- | Unfold sequentially from the right with an index aware function. -- -- @since 0.3.0-iunfoldlS_-  :: Construct DL ix e => Sz ix -> (ix -> a -> (a, e)) -> a -> Array DL ix e-iunfoldlS_ sz f acc0 =-  DLArray-    { dlComp = Seq-    , dlSize = sz-    , dlDefault = Nothing-    , dlLoad =-        \ _ startAt dlWrite ->-          void $ loopDeepM startAt (< (totalElem sz + startAt)) (+ 1) acc0 $ \ !i !acc -> do-            let (acc', e) = f (fromLinearIndex sz (i - startAt)) acc-            dlWrite i e-            pure acc'-    }+iunfoldlS_ ::+     forall ix e a. Construct DL ix e+  => Sz ix+  -> (ix -> a -> (a, e))+  -> a+  -> Array DL ix e+iunfoldlS_ sz f acc0 = DLArray {dlComp = Seq, dlSize = sz, dlDefault = Nothing, dlLoad = load}+  where+    load :: Monad m => Scheduler m () -> Int -> (Int -> e -> m ()) -> m ()+    load _ startAt dlWrite =+      void $+      loopDeepM startAt (< (totalElem sz + startAt)) (+ 1) acc0 $ \ !i !acc ->+        let (acc', e) = f (fromLinearIndex sz (i - startAt)) acc+         in acc' <$ dlWrite i e+    {-# INLINE load #-} {-# INLINE iunfoldlS_ #-}  @@ -312,28 +313,28 @@   -> Comp -- ^ Computation strategy.   -> Sz ix -- ^ Resulting size of the array.   -> Array DL ix e-randomArray gen splitGen nextRandom comp sz =-  unsafeMakeLoadArray comp sz Nothing $ \scheduler startAt writeAt ->-    splitLinearly (numWorkers scheduler) totalLength $ \chunkLength slackStart -> do-      let slackStartAt = slackStart + startAt-          writeRandom k genII = do-            let (e, genII') = nextRandom genII-            writeAt k e-            pure genII'-      genForSlack <--        loopM startAt (< slackStartAt) (+ chunkLength) gen $ \start genI -> do-          let (genI0, genI1) =-                if numWorkers scheduler == 1-                  then (genI, genI)-                  else splitGen genI-          scheduleWork_ scheduler $-            void $ loopM start (< (start + chunkLength)) (+ 1) genI0 writeRandom-          pure genI1-      when (slackStartAt < totalLength + startAt) $-        scheduleWork_ scheduler $-        void $ loopM slackStartAt (< totalLength + startAt) (+ 1) genForSlack writeRandom+randomArray gen splitGen nextRandom comp sz = unsafeMakeLoadArray comp sz Nothing load   where     !totalLength = totalElem sz+    load :: Monad m => Scheduler m () -> Int -> (Int -> e -> m ()) -> m ()+    load scheduler startAt writeAt =+      splitLinearly (numWorkers scheduler) totalLength $ \chunkLength slackStart -> do+        let slackStartAt = slackStart + startAt+            writeRandom k genII =+              let (e, genII') = nextRandom genII+               in genII' <$ writeAt k e+        genForSlack <-+          loopM startAt (< slackStartAt) (+ chunkLength) gen $ \start genI -> do+            let (genI0, genI1) =+                  if numWorkers scheduler == 1+                    then (genI, genI)+                    else splitGen genI+            scheduleWork_ scheduler $+              void $ loopM start (< (start + chunkLength)) (+ 1) genI0 writeRandom+            pure genI1+        when (slackStartAt < totalLength + startAt) $+          scheduleWork_ scheduler $+          void $ loopM slackStartAt (< totalLength + startAt) (+ 1) genForSlack writeRandom {-# INLINE randomArray #-}  -- | Similar to `randomArray` but performs generation sequentially, which means it doesn't@@ -421,7 +422,7 @@  infix 4 ..., ..: --- | Handy synonym for `rangeInclusive` `Seq`+-- | Handy synonym for @`rangeInclusive` `Seq`@. Similar to @..@ for list. -- -- >>> Ix1 4 ... 10 -- Array D Seq (Sz1 7)@@ -432,7 +433,7 @@ (...) = rangeInclusive Seq {-# INLINE (...) #-} --- | Handy synonym for `range` `Seq`+-- | Handy synonym for @`range` `Seq`@ -- -- >>> Ix1 4 ..: 10 -- Array D Seq (Sz1 6)
src/Data/Massiv/Array/Ops/Fold/Internal.hs view
@@ -311,21 +311,23 @@   -> b -- ^ Accumulator for chunks folding   -> Array r ix e   -> m b-ifoldlIO f !initAcc g !tAcc !arr = do-  let !sz = size arr-      !totalLength = totalElem sz-  results <--    withScheduler (getComp arr) $ \scheduler ->-      splitLinearly (numWorkers scheduler) totalLength $ \chunkLength slackStart -> do-        loopM_ 0 (< slackStart) (+ chunkLength) $ \ !start ->-          scheduleWork scheduler $-          iterLinearM sz start (start + chunkLength) 1 (<) initAcc $ \ !i ix !acc ->-            f acc ix (unsafeLinearIndex arr i)-        when (slackStart < totalLength) $-          scheduleWork scheduler $-          iterLinearM sz slackStart totalLength 1 (<) initAcc $ \ !i ix !acc ->-            f acc ix (unsafeLinearIndex arr i)-  F.foldlM g tAcc results+ifoldlIO f !initAcc g !tAcc !arr+  | getComp arr == Seq = ifoldlM f initAcc arr >>= g tAcc+  | otherwise = do+      let !sz = size arr+          !totalLength = totalElem sz+      results <-+        withScheduler (getComp arr) $ \scheduler ->+          splitLinearly (numWorkers scheduler) totalLength $ \chunkLength slackStart -> do+            loopM_ 0 (< slackStart) (+ chunkLength) $ \ !start ->+              scheduleWork scheduler $+              iterLinearM sz start (start + chunkLength) 1 (<) initAcc $ \ !i ix !acc ->+                f acc ix (unsafeLinearIndex arr i)+            when (slackStart < totalLength) $+              scheduleWork scheduler $+              iterLinearM sz slackStart totalLength 1 (<) initAcc $ \ !i ix !acc ->+                f acc ix (unsafeLinearIndex arr i)+      F.foldlM g tAcc results {-# INLINE ifoldlIO #-}  -- -- | Split an array into linear row-major vector chunks and apply an action to each of@@ -361,19 +363,21 @@ -- @since 0.1.0 ifoldrIO :: (MonadUnliftIO m, Source r ix e) =>            (ix -> e -> a -> m a) -> a -> (a -> b -> m b) -> b -> Array r ix e -> m b-ifoldrIO f !initAcc g !tAcc !arr = do-  let !sz = size arr-      !totalLength = totalElem sz-  results <--    withScheduler (getComp arr) $ \ scheduler ->-      splitLinearly (numWorkers scheduler) totalLength $ \ chunkLength slackStart -> do-        when (slackStart < totalLength) $-          scheduleWork scheduler $-          iterLinearM sz (totalLength - 1) slackStart (-1) (>=) initAcc $ \ !i ix !acc ->-            f ix (unsafeLinearIndex arr i) acc-        loopM_ slackStart (> 0) (subtract chunkLength) $ \ !start ->-          scheduleWork scheduler $-            iterLinearM sz (start - 1) (start - chunkLength) (-1) (>=) initAcc $ \ !i ix !acc ->+ifoldrIO f !initAcc g !tAcc !arr+  | getComp arr == Seq = ifoldrM f initAcc arr >>= (`g` tAcc)+  | otherwise = do+    let !sz = size arr+        !totalLength = totalElem sz+    results <-+      withScheduler (getComp arr) $ \ scheduler ->+        splitLinearly (numWorkers scheduler) totalLength $ \ chunkLength slackStart -> do+          when (slackStart < totalLength) $+            scheduleWork scheduler $+            iterLinearM sz (totalLength - 1) slackStart (-1) (>=) initAcc $ \ !i ix !acc ->               f ix (unsafeLinearIndex arr i) acc-  F.foldlM (flip g) tAcc results+          loopM_ slackStart (> 0) (subtract chunkLength) $ \ !start ->+            scheduleWork scheduler $+              iterLinearM sz (start - 1) (start - chunkLength) (-1) (>=) initAcc $ \ !i ix !acc ->+                f ix (unsafeLinearIndex arr i) acc+    F.foldlM (flip g) tAcc results {-# INLINE ifoldrIO #-}
src/Data/Massiv/Array/Ops/Map.hs view
@@ -52,12 +52,16 @@   -- ** Zipping   , zip   , zip3+  , zip4   , unzip   , unzip3+  , unzip4   , zipWith   , zipWith3+  , zipWith4   , izipWith   , izipWith3+  , izipWith4   , liftArray2   -- *** Applicative   , zipWithA@@ -102,6 +106,19 @@ zip3 = zipWith3 (,,) {-# INLINE zip3 #-} +-- | Zip four arrays+--+-- @since 0.5.4+zip4 ::+     (Source r1 ix e1, Source r2 ix e2, Source r3 ix e3, Source r4 ix e4)+  => Array r1 ix e1+  -> Array r2 ix e2+  -> Array r3 ix e3+  -> Array r4 ix e4+  -> Array D ix (e1, e2, e3, e4)+zip4 = zipWith4 (,,,)+{-# INLINE zip4 #-}+ -- | Unzip two arrays unzip :: Source r ix (e1, e2) => Array r ix (e1, e2) -> (Array D ix e1, Array D ix e2) unzip arr = (map fst arr, map snd arr)@@ -113,6 +130,18 @@ unzip3 arr = (map (\ (e, _, _) -> e) arr, map (\ (_, e, _) -> e) arr, map (\ (_, _, e) -> e) arr) {-# INLINE unzip3 #-} +-- | Unzip four arrays+--+-- @since 0.5.4+unzip4 :: Source r ix (e1, e2, e3, e4)+       => Array r ix (e1, e2, e3, e4) -> (Array D ix e1, Array D ix e2, Array D ix e3, Array D ix e4)+unzip4 arr =+  ( map (\(e, _, _, _) -> e) arr+  , map (\(_, e, _, _) -> e) arr+  , map (\(_, _, e, _) -> e) arr+  , map (\(_, _, _, e) -> e) arr)+{-# INLINE unzip4 #-}+ -------------------------------------------------------------------------------- -- zipWith --------------------------------------------------------------------- --------------------------------------------------------------------------------@@ -161,6 +190,48 @@           (coerce (size arr3)))) $ \ !ix ->     f ix (unsafeIndex arr1 ix) (unsafeIndex arr2 ix) (unsafeIndex arr3 ix) {-# INLINE izipWith3 #-}++++-- | Just like `zipWith`, except zip four arrays with a function.+--+-- @since 0.5.4+zipWith4 ::+     (Source r1 ix e1, Source r2 ix e2, Source r3 ix e3, Source r4 ix e4)+  => (e1 -> e2 -> e3 -> e4 -> e)+  -> Array r1 ix e1+  -> Array r2 ix e2+  -> Array r3 ix e3+  -> Array r4 ix e4+  -> Array D ix e+zipWith4 f = izipWith4 (\ _ e1 e2 e3 e4 -> f e1 e2 e3 e4)+{-# INLINE zipWith4 #-}+++-- | Just like `zipWith4`, except with an index aware function.+--+-- @since 0.5.4+izipWith4+  :: (Source r1 ix e1, Source r2 ix e2, Source r3 ix e3, Source r4 ix e4)+  => (ix -> e1 -> e2 -> e3 -> e4 -> e)+  -> Array r1 ix e1+  -> Array r2 ix e2+  -> Array r3 ix e3+  -> Array r4 ix e4+  -> Array D ix e+izipWith4 f arr1 arr2 arr3 arr4 =+  DArray+    (getComp arr1 <> getComp arr2 <> getComp arr3 <> getComp arr4)+    (SafeSz+       (liftIndex2+          min+          (liftIndex2+             min+             (liftIndex2 min (coerce (size arr1)) (coerce (size arr2)))+             (coerce (size arr3)))+          (coerce (size arr4)))) $ \ !ix ->+    f ix (unsafeIndex arr1 ix) (unsafeIndex arr2 ix) (unsafeIndex arr3 ix) (unsafeIndex arr4 ix)+{-# INLINE izipWith4 #-}   -- | Similar to `zipWith`, except does it sequentially and using the `Applicative`. Note that
src/Data/Massiv/Array/Ops/Slice.hs view
@@ -1,4 +1,6 @@ {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-} -- | -- Module      : Data.Massiv.Array.Ops.Slice -- Copyright   : (c) Alexey Kuleshevich 2018-2019@@ -21,9 +23,15 @@   , (<!>)   , (<!?>)   , (<??>)+  -- ** Many slices+  , outerSlices+  , innerSlices+  , withinSlices+  , withinSlicesM   ) where  import Control.Monad (unless)+import Data.Massiv.Array.Delayed.Pull import Data.Massiv.Core.Common  @@ -147,12 +155,20 @@ (<!?>) !arr (dim, i) = do   (m, szl) <- pullOutSzM (size arr) dim   unless (isSafeIndex m i) $ throwM $ IndexOutOfBoundsException m i-  start <- setDimM zeroIndex dim i   cutSz <- insertSzM szl dim oneSz-  unsafeSlice arr start cutSz dim+  internalInnerSlice dim cutSz arr i {-# INLINE (<!?>) #-}  +internalInnerSlice ::+     (MonadThrow m, Slice r ix e) => Dim -> Sz ix -> Array r ix e -> Int -> m (Elt r ix e)+internalInnerSlice dim cutSz arr i = do+  start <- setDimM zeroIndex dim i+  unsafeSlice arr start cutSz dim+{-# INLINE internalInnerSlice #-}+++ -- prop> arr !> i == arr <!> (dimensions (size arr), i) -- prop> arr <! i == arr <!> (1,i) --@@ -174,3 +190,120 @@ (<??>) :: (MonadThrow m, Slice r ix e) => m (Array r ix e) -> (Dim, Int) -> m (Elt r ix e) (<??>) !marr !ix = marr >>= (<!?> ix) {-# INLINE (<??>) #-}++-- | Create a delayed array of outer slices.+--+-- ====__Examples__+--+-- >>> import Data.Massiv.Array as A+-- >>> A.mapM_ print $ outerSlices (0 ..: (3 :. 2))+-- Array D Seq (Sz1 2)+--   [ 0 :. 0, 0 :. 1 ]+-- Array D Seq (Sz1 2)+--   [ 1 :. 0, 1 :. 1 ]+-- Array D Seq (Sz1 2)+--   [ 2 :. 0, 2 :. 1 ]+--+-- @since 0.5.4+outerSlices :: OuterSlice r ix e => Array r ix e -> Array D Ix1 (Elt r ix e)+outerSlices arr = makeArray Seq k (unsafeOuterSlice arr)+  where+    (k, _) = unconsSz $ size arr+-- TODO: move setComp to Load+-- outerSlices arr = makeArray (getComp arr) k (unsafeOuterSlice arr')+--   where+--     arr' = setComp Seq arr+--     (k, _) = unconsSz $ size arr+{-# INLINE outerSlices #-}+++-- | Create a delayed array of inner slices.+--+-- ====__Examples__+--+-- >>> import Data.Massiv.Array as A+-- >>> A.mapM_ print $ innerSlices (0 ..: (3 :. 2))+-- Array D Seq (Sz1 3)+--   [ 0 :. 0, 1 :. 0, 2 :. 0 ]+-- Array D Seq (Sz1 3)+--   [ 0 :. 1, 1 :. 1, 2 :. 1 ]+--+-- @since 0.5.4+innerSlices :: InnerSlice r ix e => Array r ix e -> Array D Ix1 (Elt r ix e)+innerSlices arr = makeArray Seq k (unsafeInnerSlice arr sz)+  where+    sz@(_, k) = unsnocSz $ size arr+-- TODO: move setComp to Load+-- innerSlices arr = makeArray (getComp arr) k (unsafeInnerSlice arr' sz)+--   where+--     arr' = setComp Seq arr+--     sz@(_, k) = unsnocSz $ size arr+{-# INLINE innerSlices #-}++-- | Create a delayed array of slices from within. Checks dimension at compile time.+--+-- ====__Examples__+--+-- >>> import Data.Massiv.Array as A+-- >>> arr = fromIx3 <$> (0 ..: (4 :> 3 :. 2))+-- >>> print arr+-- Array D Seq (Sz (4 :> 3 :. 2))+--   [ [ [ (0,0,0), (0,0,1) ]+--     , [ (0,1,0), (0,1,1) ]+--     , [ (0,2,0), (0,2,1) ]+--     ]+--   , [ [ (1,0,0), (1,0,1) ]+--     , [ (1,1,0), (1,1,1) ]+--     , [ (1,2,0), (1,2,1) ]+--     ]+--   , [ [ (2,0,0), (2,0,1) ]+--     , [ (2,1,0), (2,1,1) ]+--     , [ (2,2,0), (2,2,1) ]+--     ]+--   , [ [ (3,0,0), (3,0,1) ]+--     , [ (3,1,0), (3,1,1) ]+--     , [ (3,2,0), (3,2,1) ]+--     ]+--   ]+-- >>> A.mapM_ print $ withinSlices Dim2 arr+-- Array D Seq (Sz (4 :. 2))+--   [ [ (0,0,0), (0,0,1) ]+--   , [ (1,0,0), (1,0,1) ]+--   , [ (2,0,0), (2,0,1) ]+--   , [ (3,0,0), (3,0,1) ]+--   ]+-- Array D Seq (Sz (4 :. 2))+--   [ [ (0,1,0), (0,1,1) ]+--   , [ (1,1,0), (1,1,1) ]+--   , [ (2,1,0), (2,1,1) ]+--   , [ (3,1,0), (3,1,1) ]+--   ]+-- Array D Seq (Sz (4 :. 2))+--   [ [ (0,2,0), (0,2,1) ]+--   , [ (1,2,0), (1,2,1) ]+--   , [ (2,2,0), (2,2,1) ]+--   , [ (3,2,0), (3,2,1) ]+--   ]+--+-- @since 0.5.4+withinSlices ::+     (IsIndexDimension ix n, Slice r ix e)+  => Dimension n+  -> Array r ix e+  -> Array D Ix1 (Elt r ix e)+withinSlices dim = either throwImpossible id . withinSlicesM (fromDimension dim)+{-# INLINE withinSlices #-}+++-- | Create a delayed array of slices from within. Same as `withinSlices`, but throws an+-- error on invalid dimension.+--+-- /__Throws Exceptions__/: `IndexDimensionException`+--+-- @since 0.5.4+withinSlicesM :: (MonadThrow m, Slice r ix e) => Dim -> Array r ix e -> m (Array D Ix1 (Elt r ix e))+withinSlicesM dim arr = do+  (k, szl) <- pullOutSzM (size arr) dim+  cutSz <- insertSzM szl dim oneSz+  pure $ makeArray Seq k (either throwImpossible id . internalInnerSlice dim cutSz arr)+{-# INLINE withinSlicesM #-}
src/Data/Massiv/Array/Ops/Transform.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE BangPatterns #-}-{-# LANGUAGE ExplicitForAll #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} {-# OPTIONS_GHC -fno-warn-redundant-constraints #-} -- |@@ -43,6 +43,9 @@   , concatOuterM   , concatM   , concat'+  , stackSlicesM+  , stackOuterSlicesM+  , stackInnerSlicesM   , splitAtM   , splitAt'   , splitExtractM@@ -62,7 +65,7 @@ import Control.Scheduler (traverse_) import Control.Monad as M (foldM_, unless, forM_) import Data.Bifunctor (bimap)-import Data.Foldable as F (foldl', foldrM, toList)+import Data.Foldable as F (foldl', foldrM, toList, length) import qualified Data.List as L (uncons) import Data.Massiv.Array.Delayed.Pull import Data.Massiv.Array.Delayed.Push@@ -393,7 +396,7 @@ -- an allowed exception of the dimension they are being appended along, otherwise `Nothing` is -- returned. ----- ===__Examples__+-- ====__Examples__ -- -- Append two 2D arrays along both dimensions. Note that they do agree on inner dimensions. --@@ -425,32 +428,34 @@ -- *** Exception: SizeMismatchException: (Sz (2 :. 3)) vs (Sz (2 :. 4)) -- -- @since 0.3.0-appendM :: (MonadThrow m, Source r1 ix e, Source r2 ix e) =>-          Dim -> Array r1 ix e -> Array r2 ix e -> m (Array DL ix e)+appendM ::+     forall r1 r2 ix e m. (MonadThrow m, Source r1 ix e, Source r2 ix e)+  => Dim+  -> Array r1 ix e+  -> Array r2 ix e+  -> m (Array DL ix e) appendM n !arr1 !arr2 = do   let !sz1 = size arr1       !sz2 = size arr2   (k1, szl1) <- pullOutSzM sz1 n   (k2, szl2) <- pullOutSzM sz2 n   unless (szl1 == szl2) $ throwM $ SizeMismatchException sz1 sz2-  let k1' = unSz k1+  let !k1' = unSz k1   newSz <- insertSzM szl1 n (SafeSz (k1' + unSz k2))+  let load :: Monad n => Scheduler n () -> Int -> (Int -> e -> n ()) -> n ()+      load scheduler !startAt dlWrite = do+        scheduleWork scheduler $+          iterM_ zeroIndex (unSz sz1) (pureIndex 1) (<) $ \ix ->+            dlWrite (startAt + toLinearIndex newSz ix) (unsafeIndex arr1 ix)+        scheduleWork scheduler $+          iterM_ zeroIndex (unSz sz2) (pureIndex 1) (<) $ \ix ->+            let i = getDim' ix n+                ix' = setDim' ix n (i + k1')+             in dlWrite (startAt + toLinearIndex newSz ix') (unsafeIndex arr2 ix)+      {-# INLINE load #-}   return $     DLArray-      { dlComp = getComp arr1 <> getComp arr2-      , dlSize = newSz-      , dlDefault = Nothing-      , dlLoad =-          \scheduler startAt dlWrite -> do-            scheduleWork scheduler $-              iterM_ zeroIndex (unSz sz1) (pureIndex 1) (<) $ \ix ->-                dlWrite (startAt + toLinearIndex newSz ix) (unsafeIndex arr1 ix)-            scheduleWork scheduler $-              iterM_ zeroIndex (unSz sz2) (pureIndex 1) (<) $ \ix ->-                let i = getDim' ix n-                    ix' = setDim' ix n (i + k1')-                 in dlWrite (startAt + toLinearIndex newSz ix') (unsafeIndex arr2 ix)-      }+      {dlComp = getComp arr1 <> getComp arr2, dlSize = newSz, dlDefault = Nothing, dlLoad = load} {-# INLINE appendM #-}  @@ -476,13 +481,16 @@ -- -- @since 0.3.0 concatM ::-     (MonadThrow m, Foldable f, Source r ix e) => Dim -> f (Array r ix e) -> m (Array DL ix e)+     forall r ix e f m. (MonadThrow m, Foldable f, Source r ix e)+  => Dim+  -> f (Array r ix e)+  -> m (Array DL ix e) concatM n !arrsF =   case L.uncons (F.toList arrsF) of     Nothing -> pure empty     Just (a, arrs) -> do       let sz = unSz (size a)-          szs = P.map (unSz . size) arrs+          szs = unSz . size <$> arrs       (k, szl) <- pullOutDimM sz n       -- / remove the dimension out of all sizes along which concatenation will happen       (ks, szls) <-@@ -493,25 +501,192 @@         (dropWhile ((== szl) . snd) $ P.zip szs szls)       let kTotal = SafeSz $ F.foldl' (+) k ks       newSz <- insertSzM (SafeSz szl) n kTotal+      let load :: Monad n => Scheduler n () -> Int -> (Int -> e -> n ()) -> n ()+          load scheduler startAt dlWrite =+            let arrayLoader !kAcc (kCur, arr) = do+                  scheduleWork scheduler $+                    iforM_ arr $ \ix e ->+                      let i = getDim' ix n+                          ix' = setDim' ix n (i + kAcc)+                       in dlWrite (startAt + toLinearIndex newSz ix') e+                  pure (kAcc + kCur)+             in M.foldM_ arrayLoader 0 $ (k, a) : P.zip ks arrs+          {-# INLINE load #-}       return $-        DLArray-          { dlComp = mconcat $ P.map getComp arrs-          , dlSize = newSz-          , dlDefault = Nothing-          , dlLoad =-              \scheduler startAt dlWrite ->-                let arrayLoader !kAcc (kCur, arr) = do-                      scheduleWork scheduler $-                        iterM_ zeroIndex (unSz (size arr)) (pureIndex 1) (<) $ \ix ->-                          let i = getDim' ix n-                              ix' = setDim' ix n (i + kAcc)-                           in dlWrite (startAt + toLinearIndex newSz ix') (unsafeIndex arr ix)-                      pure (kAcc + kCur)-                 in M.foldM_ arrayLoader 0 $ (k, a) : P.zip ks arrs-          }+        DLArray {dlComp = foldMap getComp arrsF, dlSize = newSz, dlDefault = Nothing, dlLoad = load} {-# INLINE concatM #-}  +-- | Stack slices on top of each other along the specified dimension.+--+-- /__Exceptions__/: `IndexDimensionException`, `SizeMismatchException`+--+-- ====__Examples__+--+-- Here are the three different ways to stack up two 2D Matrix pages into a 3D array.+--+-- >>> import Data.Massiv.Array as A+-- >>> x = compute (iterateN 3 succ 0) :: Matrix P Int+-- >>> y = compute (iterateN 3 succ 9) :: Matrix P Int+-- >>> x+-- Array P Seq (Sz (3 :. 3))+--   [ [ 1, 2, 3 ]+--   , [ 4, 5, 6 ]+--   , [ 7, 8, 9 ]+--   ]+-- >>> y+-- Array P Seq (Sz (3 :. 3))+--   [ [ 10, 11, 12 ]+--   , [ 13, 14, 15 ]+--   , [ 16, 17, 18 ]+--   ]+-- >>> stackSlicesM 1 [x, y] :: IO (Array DL Ix3 Int)+-- Array DL Seq (Sz (3 :> 3 :. 2))+--   [ [ [ 1, 10 ]+--     , [ 2, 11 ]+--     , [ 3, 12 ]+--     ]+--   , [ [ 4, 13 ]+--     , [ 5, 14 ]+--     , [ 6, 15 ]+--     ]+--   , [ [ 7, 16 ]+--     , [ 8, 17 ]+--     , [ 9, 18 ]+--     ]+--   ]+-- >>> stackSlicesM 2 [x, y] :: IO (Array DL Ix3 Int)+-- Array DL Seq (Sz (3 :> 2 :. 3))+--   [ [ [ 1, 2, 3 ]+--     , [ 10, 11, 12 ]+--     ]+--   , [ [ 4, 5, 6 ]+--     , [ 13, 14, 15 ]+--     ]+--   , [ [ 7, 8, 9 ]+--     , [ 16, 17, 18 ]+--     ]+--   ]+-- >>> stackSlicesM 3 [x, y] :: IO (Array DL Ix3 Int)+-- Array DL Seq (Sz (2 :> 3 :. 3))+--   [ [ [ 1, 2, 3 ]+--     , [ 4, 5, 6 ]+--     , [ 7, 8, 9 ]+--     ]+--   , [ [ 10, 11, 12 ]+--     , [ 13, 14, 15 ]+--     , [ 16, 17, 18 ]+--     ]+--   ]+--+-- @since 0.5.4+stackSlicesM ::+     forall r ix e f m. (Foldable f, MonadThrow m, Source r (Lower ix) e, Index ix)+  => Dim+  -> f (Array r (Lower ix) e)+  -> m (Array DL ix e)+stackSlicesM dim !arrsF = do+  case L.uncons (F.toList arrsF) of+    Nothing -> pure empty+    Just (a, arrs) -> do+      let sz = size a+          len = SafeSz (F.length arrsF)+      -- / make sure all arrays have the same size+      M.forM_ arrsF $ \arr ->+        let sz' = size arr+         in unless (sz == sz') $ throwM (SizeMismatchException sz sz')+      newSz <- insertSzM sz dim len+      let load :: Monad n => Scheduler n () -> Int -> (Int -> e -> n ()) -> n ()+          load scheduler startAt dlWrite =+            let loadIndex k ix = dlWrite (toLinearIndex newSz (insertDim' ix dim k) + startAt)+                arrayLoader !k arr = (k + 1) <$ scheduleWork scheduler (imapM_ (loadIndex k) arr)+             in M.foldM_ arrayLoader 0 arrsF+          {-# INLINE load #-}+      return $+        DLArray {dlComp = foldMap getComp arrs, dlSize = newSz, dlDefault = Nothing, dlLoad = load}+{-# INLINE stackSlicesM #-}++-- | Specialized `stackOuterM` to handling stacking from the outside. It is the inverse of+-- `Data.Massiv.Array.outerSlices`.+--+-- /__Exceptions__/: `SizeMismatchException`+--+-- ====__Examples__+--+-- In this example we stack vectors as row of a matrix from top to bottom:+--+-- >>> import Data.Massiv.Array as A+-- >>> x = compute (iterateN 3 succ 0) :: Matrix P Int+-- >>> x+-- Array P Seq (Sz (3 :. 3))+--   [ [ 1, 2, 3 ]+--   , [ 4, 5, 6 ]+--   , [ 7, 8, 9 ]+--   ]+-- >>> rows = outerSlices x+-- >>> A.mapM_ print rows+-- Array M Seq (Sz1 3)+--   [ 1, 2, 3 ]+-- Array M Seq (Sz1 3)+--   [ 4, 5, 6 ]+-- Array M Seq (Sz1 3)+--   [ 7, 8, 9 ]+-- >>> stackOuterSlicesM rows :: IO (Matrix DL Int)+-- Array DL Seq (Sz (3 :. 3))+--   [ [ 1, 2, 3 ]+--   , [ 4, 5, 6 ]+--   , [ 7, 8, 9 ]+--   ]+--+-- @since 0.5.4+stackOuterSlicesM ::+     forall r ix e f m. (Foldable f, MonadThrow m, Source r (Lower ix) e, Index ix)+  => f (Array r (Lower ix) e)+  -> m (Array DL ix e)+stackOuterSlicesM = stackSlicesM (dimensions (Proxy :: Proxy ix))+{-# INLINE stackOuterSlicesM #-}++-- | Specialized `stackOuterM` to handling stacking from the inside. It is the inverse of+-- `Data.Massiv.Array.outerSlices`.+--+-- /__Exceptions__/: `SizeMismatchException`+--+-- ====__Examples__+--+-- In this example we stack vectors as columns of a matrix from left to right:+--+-- >>> import Data.Massiv.Array as A+-- >>> x = compute (iterateN 3 succ 0) :: Matrix P Int+-- >>> x+-- Array P Seq (Sz (3 :. 3))+--   [ [ 1, 2, 3 ]+--   , [ 4, 5, 6 ]+--   , [ 7, 8, 9 ]+--   ]+-- >>> columns = innerSlices x+-- >>> A.mapM_ print columns+-- Array M Seq (Sz1 3)+--   [ 1, 4, 7 ]+-- Array M Seq (Sz1 3)+--   [ 2, 5, 8 ]+-- Array M Seq (Sz1 3)+--   [ 3, 6, 9 ]+-- >>> stackInnerSlicesM columns :: IO (Matrix DL Int)+-- Array DL Seq (Sz (3 :. 3))+--   [ [ 1, 2, 3 ]+--   , [ 4, 5, 6 ]+--   , [ 7, 8, 9 ]+--   ]+--+-- @since 0.5.4+stackInnerSlicesM ::+     forall r ix e f m. (Foldable f, MonadThrow m, Source r (Lower ix) e, Index ix)+  => f (Array r (Lower ix) e)+  -> m (Array DL ix e)+stackInnerSlicesM = stackSlicesM 1+{-# INLINE stackInnerSlicesM #-}++ -- | /O(1)/ - Split an array into two at an index along a specified dimension. -- -- /Related/: `splitAt'`, `splitExtractM`, `Data.Massiv.Vector.sliceAt'`, `Data.Massiv.Vector.sliceAtM`@@ -669,51 +844,84 @@ -- | Discard elements from the source array according to the stride. -- -- @since 0.3.0-downsample :: Source r ix e => Stride ix -> Array r ix e -> Array DL ix e+downsample ::+     forall r ix e. Source r ix e+  => Stride ix+  -> Array r ix e+  -> Array DL ix e downsample stride arr =-  DLArray-    { dlComp = getComp arr-    , dlSize = resultSize-    , dlDefault = defaultElement arr-    , dlLoad =-        \scheduler startAt dlWrite ->-          splitLinearlyWithStartAtM_-            scheduler-            startAt-            (totalElem resultSize)-            (pure . unsafeLinearWriteWithStride)-            dlWrite-    }+  DLArray {dlComp = getComp arr, dlSize = resultSize, dlDefault = defaultElement arr, dlLoad = load}   where     resultSize = strideSize stride (size arr)     strideIx = unStride stride     unsafeLinearWriteWithStride =       unsafeIndex arr . liftIndex2 (*) strideIx . fromLinearIndex resultSize     {-# INLINE unsafeLinearWriteWithStride #-}+    load :: Monad m => Scheduler m () -> Int -> (Int -> e -> m ()) -> m ()+    load scheduler startAt dlWrite =+      splitLinearlyWithStartAtM_+        scheduler+        startAt+        (totalElem resultSize)+        (pure . unsafeLinearWriteWithStride)+        dlWrite+    {-# INLINE load #-} {-# INLINE downsample #-}  --- | Insert the same element into a `Load`able array according to the stride.+-- | Insert the same element into a `Load`able array according to the supplied stride. --+-- ====__Examples__+--+-- >>> import Data.Massiv.Array as A+-- >>> arr = iterateN (Sz2 3 2) succ (0 :: Int)+-- >>> arr+-- Array DL Seq (Sz (3 :. 2))+--   [ [ 1, 2 ]+--   , [ 3, 4 ]+--   , [ 5, 6 ]+--   ]+-- >>> upsample 0 (Stride (2 :. 3)) arr+-- Array DL Seq (Sz (6 :. 6))+--   [ [ 1, 0, 0, 2, 0, 0 ]+--   , [ 0, 0, 0, 0, 0, 0 ]+--   , [ 3, 0, 0, 4, 0, 0 ]+--   , [ 0, 0, 0, 0, 0, 0 ]+--   , [ 5, 0, 0, 6, 0, 0 ]+--   , [ 0, 0, 0, 0, 0, 0 ]+--   ]+-- >>> upsample 9 (Stride (1 :. 2)) arr+-- Array DL Seq (Sz (3 :. 4))+--   [ [ 1, 9, 2, 9 ]+--   , [ 3, 9, 4, 9 ]+--   , [ 5, 9, 6, 9 ]+--   ]+-- -- @since 0.3.0-upsample-  :: Load r ix e => e -> Stride ix -> Array r ix e -> Array DL ix e+upsample ::+     forall r ix e. Load r ix e+  => e -- ^ Element to use for filling the newly added cells+  -> Stride ix -- ^ Fill cells according to this stride+  -> Array r ix e -- ^ Array that will have cells added to+  -> Array DL ix e upsample !fillWith safeStride arr =   DLArray     { dlComp = getComp arr     , dlSize = newsz     , dlDefault = Just fillWith-    , dlLoad =-        \scheduler startAt dlWrite -> do-          M.forM_ (defaultElement arr) $ \prevFillWith ->-            loopM_-              startAt-              (< totalElem sz)-              (+ 1)-              (\i -> dlWrite (adjustLinearStride (i + startAt)) prevFillWith)-          loadArrayM scheduler arr (\i -> dlWrite (adjustLinearStride (i + startAt)))+    , dlLoad = load     }   where+    load :: Monad m => Scheduler m () -> Int -> (Int -> e -> m ()) -> m ()+    load scheduler !startAt dlWrite = do+      M.forM_ (defaultElement arr) $ \prevFillWith ->+        loopM_+          startAt+          (< totalElem sz)+          (+ 1)+          (\i -> dlWrite (adjustLinearStride (i + startAt)) prevFillWith)+      loadArrayM scheduler arr (\i -> dlWrite (adjustLinearStride (i + startAt)))+    {-# INLINE load #-}     adjustLinearStride = toLinearIndex newsz . timesStride . fromLinearIndex sz     {-# INLINE adjustLinearStride #-}     timesStride !ix = liftIndex2 (*) stride ix@@ -819,21 +1027,23 @@ -- -- @since 0.3.1 zoomWithGrid ::-     Source r ix e+     forall r ix e. Source r ix e   => e -- ^ Value to use for the grid   -> Stride ix -- ^ Scaling factor   -> Array r ix e -- ^ Source array   -> Array DL ix e-zoomWithGrid gridVal (Stride zoomFactor) arr =-  unsafeMakeLoadArray Seq newSz (Just gridVal) $ \scheduler _ writeElement ->-    iforSchedulerM_ scheduler arr $ \ !ix !e -> do-      let !kix = liftIndex2 (*) ix kx-      mapM_ (\ !ix' -> writeElement (toLinearIndex newSz ix') e) $-        range Seq (liftIndex (+1) kix) (liftIndex2 (+) kix kx)+zoomWithGrid gridVal (Stride zoomFactor) arr = unsafeMakeLoadArray Seq newSz (Just gridVal) load   where-    !kx = liftIndex (+1) zoomFactor+    !kx = liftIndex (+ 1) zoomFactor     !lastNewIx = liftIndex2 (*) kx $ unSz (size arr)-    !newSz = Sz (liftIndex (+1) lastNewIx)+    !newSz = Sz (liftIndex (+ 1) lastNewIx)+    load :: Monad m => Scheduler m () -> Int -> (Int -> e -> m ()) -> m ()+    load scheduler _ writeElement =+      iforSchedulerM_ scheduler arr $ \ !ix !e ->+        let !kix = liftIndex2 (*) ix kx+         in mapM_ (\ !ix' -> writeElement (toLinearIndex newSz ix') e) $+            range Seq (liftIndex (+ 1) kix) (liftIndex2 (+) kix kx)+    {-# INLINE load #-} {-# INLINE zoomWithGrid #-}  -- | Increaze the size of the array accoridng to the stride multiplier while replicating@@ -871,17 +1081,19 @@ -- -- @since 0.4.4 zoom ::-     Source r ix e+     forall r ix e. Source r ix e   => Stride ix -- ^ Scaling factor   -> Array r ix e -- ^ Source array   -> Array DL ix e-zoom (Stride zoomFactor) arr =-  unsafeMakeLoadArray Seq newSz Nothing $ \scheduler _ writeElement ->-    iforSchedulerM_ scheduler arr $ \ !ix !e -> do-      let !kix = liftIndex2 (*) ix zoomFactor-      mapM_ (\ !ix' -> writeElement (toLinearIndex newSz ix') e) $-        range Seq kix (liftIndex2 (+) kix zoomFactor)+zoom (Stride zoomFactor) arr = unsafeMakeLoadArray Seq newSz Nothing load   where     !lastNewIx = liftIndex2 (*) zoomFactor $ unSz (size arr)     !newSz = Sz lastNewIx+    load :: Monad m => Scheduler m () -> Int -> (Int -> e -> m ()) -> m ()+    load scheduler _ writeElement =+      iforSchedulerM_ scheduler arr $ \ !ix !e ->+        let !kix = liftIndex2 (*) ix zoomFactor+         in mapM_ (\ !ix' -> writeElement (toLinearIndex newSz ix') e) $+            range Seq kix (liftIndex2 (+) kix zoomFactor)+    {-# INLINE load #-} {-# INLINE zoom #-}
src/Data/Massiv/Array/Stencil.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeFamilies #-}@@ -274,6 +275,7 @@ idStencil = makeUnsafeStencil oneSz zeroIndex $ \ _ get -> get zeroIndex {-# INLINE idStencil #-} + -- | Stencil that does a left fold in a row-major order. Regardless of the supplied size -- resulting stencil will be centered at zero, although by using `Padding` it is possible -- to overcome this limitation.@@ -334,6 +336,9 @@ {-# INLINE foldrStencil #-}  +-- | Create a stencil that will fold all elements in the region monoidally.+--+-- @since 0.4.3 foldStencil :: (Monoid e, Index ix) => Sz ix -> Stencil ix e e foldStencil = foldlStencil mappend mempty {-# INLINE foldStencil #-}
src/Data/Massiv/Array/Stencil/Internal.hs view
@@ -35,6 +35,7 @@   , stencilFunc   :: (ix -> Value e) -> ix -> Value a   } + instance Index ix => NFData (Stencil ix e a) where   rnf (Stencil sz ix f) = sz `deepseq` ix `deepseq` f `seq` () 
src/Data/Massiv/Array/Stencil/Unsafe.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RecordWildCards #-} -- | -- Module      : Data.Massiv.Array.Stencil.Unsafe -- Copyright   : (c) Alexey Kuleshevich 2018-2019@@ -13,6 +14,7 @@ module Data.Massiv.Array.Stencil.Unsafe   ( -- * Stencil     makeUnsafeStencil+  , unsafeTransformStencil   , unsafeMapStencil   -- ** Deprecated   , mapStencilUnsafe@@ -123,3 +125,80 @@       Value $ inline $ relStencil ix (unValue . getVal . liftIndex2 (+) ix)     {-# INLINE stencil #-} {-# INLINE makeUnsafeStencil #-}+++-- | Perform an arbitrary transformation of a stencil. This stencil modifier can be used for+-- example to turn a vector stencil into a matrix stencil implement, or transpose a matrix+-- stencil. It is really easy to get this wrong, so be extremely careful.+--+-- ====__Examples__+--+-- Convert a 1D stencil into a row or column 2D stencil:+--+-- >>> import Data.Massiv.Array+-- >>> import Data.Massiv.Array.Unsafe+-- >>> let arr = compute $ iterateN 3 succ 0 :: Array P Ix2 Int+-- >>> arr+-- Array P Seq (Sz (3 :. 3))+--   [ [ 1, 2, 3 ]+--   , [ 4, 5, 6 ]+--   , [ 7, 8, 9 ]+--   ]+-- >>> let rowStencil = unsafeTransformStencil (\(Sz n) -> Sz (1 :. n)) (0 :.) $ \ f getVal (i :. j) -> f (getVal . (i :.)) j+-- >>> applyStencil noPadding (rowStencil (sumStencil (Sz1 3))) arr+-- Array DW Seq (Sz (3 :. 1))+--   [ [ 6 ]+--   , [ 15 ]+--   , [ 24 ]+--   ]+-- >>> let columnStencil = unsafeTransformStencil (\(Sz n) -> Sz (n :. 1)) (:. 0) $ \ f getVal (i :. j) -> f (getVal . (:. j)) i+-- >>> applyStencil noPadding (columnStencil (sumStencil (Sz1 3))) arr+-- Array DW Seq (Sz (1 :. 3))+--   [ [ 12, 15, 18 ]+--   ]+--+-- @since 0.5.4+unsafeTransformStencil ::+     (Sz ix' -> Sz ix)+  -- ^ Forward modifier for the size+  -> (ix' -> ix)+  -- ^ Forward index modifier+  -> (((ix' -> Value e) -> ix' -> Value a) -> (ix -> Value e) -> ix -> Value a)+  -- ^ Inverse stencil function modifier+  -> Stencil ix' e a+  -- ^ Original stencil.+  -> Stencil ix e a+unsafeTransformStencil transformSize transformIndex transformFunc Stencil {..} =+  Stencil+    { stencilSize = transformSize stencilSize+    , stencilCenter = transformIndex stencilCenter+    , stencilFunc = transformFunc stencilFunc+    }+{-# INLINE unsafeTransformStencil #-}++++{-++Invalid stencil transformer function.++TODO: figure out if there is a safe way to do stencil index trnasformation.+++transformStencil ::+     (Default e, Index ix)+  => (Sz ix' -> Sz ix)+  -- ^ Forward modifier for the size+  -> (ix' -> ix)+  -- ^ Forward index modifier+  -> (ix -> ix')+  -- ^ Inverse index modifier+  -> Stencil ix' e a+  -- ^ Original stencil.+  -> Stencil ix e a+transformStencil transformSize transformIndex transformIndex' stencil =+  validateStencil def $! unsafeTransformStencil transformSize transformIndex transformIndex' stencil+{-# INLINE transformStencil #-}+++-}
src/Data/Massiv/Core/Common.hs view
@@ -235,7 +235,7 @@   -- | Arrays that can be used as source to practically any manipulation function.-class Load r ix e => Source r ix e where+class (Resize r ix, Load r ix e) => Source r ix e where   {-# MINIMAL (unsafeIndex|unsafeLinearIndex), unsafeLinearSlice #-}    -- | Lookup element in the array. No bounds check is performed and access of@@ -392,7 +392,7 @@ -- | Manifest arrays are backed by actual memory and values are looked up versus -- computed as it is with delayed arrays. Because of this fact indexing functions -- @(`!`)@, @(`!?`)@, etc. are constrained to manifest arrays only.-class (Load r ix e, Source r ix e) => Manifest r ix e where+class Source r ix e => Manifest r ix e where    unsafeLinearIndexM :: Array r ix e -> Int -> e 
src/Data/Massiv/Vector.hs view
@@ -959,12 +959,9 @@ cons :: Load r Ix1 e => e -> Vector r e -> Vector DL e cons e v =   let dv = toLoadArray v-   in dv-        { dlSize = SafeSz (1 + unSz (dlSize dv))-        , dlLoad =-            \scheduler startAt uWrite ->-              uWrite startAt e >> dlLoad dv scheduler (startAt + 1) uWrite-        }+      load scheduler startAt uWrite = uWrite startAt e >> dlLoad dv scheduler (startAt + 1) uWrite+      {-# INLINE load #-}+   in dv {dlSize = SafeSz (1 + unSz (dlSize dv)), dlLoad = load} {-# INLINE cons #-}  -- | /O(1)/ - Add an element to the vector from the right side@@ -974,12 +971,9 @@ snoc v e =   let dv = toLoadArray v       !k = unSz (size dv)-   in dv-        { dlSize = SafeSz (1 + k)-        , dlLoad =-            \scheduler startAt uWrite ->-              dlLoad dv scheduler startAt uWrite >> uWrite (k + startAt) e-        }+      load scheduler startAt uWrite = dlLoad dv scheduler startAt uWrite >> uWrite (k + startAt) e+      {-# INLINE load #-}+   in dv {dlSize = SafeSz (1 + k), dlLoad = load} {-# INLINE snoc #-}  @@ -1433,7 +1427,7 @@  -- | Similar to `filterM`, but map with an index aware function. ----- Corresponds to: @filterM (uncurry f) . imap (,)@+-- Corresponds to: @`filterM` (uncurry f) . `simap` (,)@ -- -- ==== __Examples__ --