packages feed

massiv 0.3.1.0 → 0.3.2.0

raw patch · 9 files changed

+421/−27 lines, 9 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ Data.Massiv.Array: quicksort :: (Mutable r Ix1 e, Ord e) => Array r Ix1 e -> Array r Ix1 e
+ Data.Massiv.Array.Mutable: withMArrayS :: (Mutable r ix e, PrimMonad m) => Array r ix e -> (MArray (PrimState m) r ix e -> m a) -> m (Array r ix e)
+ Data.Massiv.Array.Mutable.Algorithms: quicksortM_ :: (Ord e, Mutable r Ix1 e, PrimMonad m) => Scheduler m () -> MArray (PrimState m) r Ix1 e -> m ()
+ Data.Massiv.Array.Mutable.Algorithms: unstablePartitionM :: forall r e m. (Mutable r Ix1 e, PrimMonad m) => MArray (PrimState m) r Ix1 e -> (e -> Bool) -> m Ix1
+ Data.Massiv.Array.Unsafe: unsafeUnstablePartitionRegionM :: forall r e m. (Mutable r Ix1 e, PrimMonad m) => MArray (PrimState m) r Ix1 e -> (e -> Bool) -> Ix1 -> Ix1 -> m Ix1
- Data.Massiv.Array.Mutable: modify' :: (Mutable r ix e, MonadThrow m, PrimMonad m) => MArray (PrimState m) r ix e -> (e -> e) -> ix -> m ()
+ Data.Massiv.Array.Mutable: modify' :: (Mutable r ix e, PrimMonad m) => MArray (PrimState m) r ix e -> (e -> e) -> ix -> m ()
- Data.Massiv.Array.Mutable: read' :: (Mutable r ix e, MonadThrow m, PrimMonad m) => MArray (PrimState m) r ix e -> ix -> m e
+ Data.Massiv.Array.Mutable: read' :: (Mutable r ix e, PrimMonad m) => MArray (PrimState m) r ix e -> ix -> m e
- Data.Massiv.Array.Mutable: swap' :: (Mutable r ix e, MonadThrow m, PrimMonad m) => MArray (PrimState m) r ix e -> ix -> ix -> m ()
+ Data.Massiv.Array.Mutable: swap' :: (Mutable r ix e, PrimMonad m) => MArray (PrimState m) r ix e -> ix -> ix -> m ()
- Data.Massiv.Array.Mutable: write' :: (Mutable r ix e, MonadThrow m, PrimMonad m) => MArray (PrimState m) r ix e -> ix -> e -> m ()
+ Data.Massiv.Array.Mutable: write' :: (Mutable r ix e, PrimMonad m) => MArray (PrimState m) r ix e -> ix -> e -> m ()

Files

+ CHANGELOG.md view
@@ -0,0 +1,185 @@+# 0.3.2++* Exported `withMArrayS`+* Switch to pure exception throwing for `read'`, `write'`, `modify'` and `swap'`. `MonadThrow`+  constraint prevented those functions to be used in `ST` monad.+* Addition of `quicksort`, `quicksortM_`, `unstablePartitionRegionM` and+  `unsafeUnstablePartitionRegionM`++# 0.3.1++* Addition of `rangeStepInclusive'`+* Addition of `flatten`+* `makeLoadArray` has been deprecated into `unsafeMakeLoadArray`.+* A new safe `makeLoadArrayS` has been aded.+* Fix `infix 4` for `(...)` and `(..:)` range functions, so they can be easily composed with+  numeric operations+* Addition of `imapSchedulerM_` and `iforSchedulerM_`++# 0.3.0++* Class hierarchy an associated methods:+  * `getComp` moved from `Construct` to `Load`+  * `Size` class lost array value parameter `e`. `unsafeResize` and `unsafeExtract` became their own+    classes+* New classes:+  * `Resize` with `unsafeResize` from old `Size`, except with `array` type parameter for+    applicability to mutable `MArray`s+  * `Extract` with `unsafeExtract` from old `Size`+  * `StrideLoad`, child of `Load`+* `ifoldlIO` and related no longer take list of capabilities, but instead respect the inner+  computation strategy. For that reason these folds have been removed: `foldlOnP`, `ifoldlOnP`,+  `foldrOnP`, `ifoldrOnP`+* `fold` now is just like the one from `Data.Foldable` takes no arguments and requires elements to+  be a monoid+* `singleton` does not accept computation strategy any more and creates `Seq` array by default+* New function `empty`.+* `Ragged` functions are no longer exported, until the interface stabilizes and proper+  implementation of ragged arrays is in place.+* Partial functions `read'`, `write'` and `swap'` now live in IO and throw proper exceptions.+* `loadArray` is renamed to `loadArrayM` and there is a new separate function (not part of `Load`+  class) with the name `loadArray` that actually uses `loadArrayM`+* Moved `unsafeWithPtr` into `Data.Massiv.Array.Unsafe`+* Addition of:+  * `unsafeArrayToForeignPtr`,+  * `unsafeMArrayToForeignPtr`,+  * `unsafeArrayFromForeignPtr`,+  * `unsafeArrayFromForeignPtr0`,+  * `unsafeMArrayFromForeignPtr`,+  * `unsafeMArrayFromForeignPtr0`+* Addition of `castToByteString`, `castFromByteString`+* Addition of `makeUnsafeStencil`+* `Window` now has an `windowUnrollIx2` field.+* Addition of `insertWindow` and `dropWindow`++# 0.2.8++* Fixed a problem where convolution stencil size was not inverted, causing out of bounds memory+  read: [#72](https://github.com/lehins/massiv/issues/72)+* Fixed an issue with windowed array where a stencil size is smaller than the array it is applied to+* Fixed incorrect cross-correlation stencil construction++# 0.2.7++* Fixed a serious performance regression in `Stencil`'s `Functor` instance, which was introduced in+  version `0.2.3`+* Added type and pattern synonyms `Sz` for future compatibility with version `0.3`. Could be useful+  for migration.++# 0.2.6++* Add `expand*` family of functions.+* Long awaited `makeArrayM`/`makeArrayA` and `mapM`/`forM`/`imapM`/`iforM`/`traverseA`/`itraverseA`+  alnog with corresponding functions allowing for supplying representation.+* Deprecate `mapP` and `mapP_` in favor of `mapIO` and `mapIO_`, while making latter respect the+  `Comp`.+* Addition of a whole collection of mutable operators:+  * `mapIO`/`mapIO_`/`imapIO`/`imapIO_`/`forIO`/`forIO_`/`iforIO`/`iforIO_`+  * `createArray`/`createArrayST`/`createArrayST_`+  * `generateArray`/`generateArrayIO`+  * `unfoldlPrim`/`unfoldlPrim_`+  * `makeArrayA`, `makeArrayAR`+* Addition of cute synonyms: `(...)` and `(..:)`++# 0.2.5++* Fix for `insertDimension` [#62](https://github.com/lehins/massiv/pull/62)++# 0.2.4.1++* Fix a bug in `zip` functions, where resulting array size would not take into account the size of+  one of the input arrays.+++# 0.2.4++* Addition of inner folds: `ifoldlInner`, `foldlInner`, `ifoldrInner` and `foldrInner`+* Addition of functions that can fold over any dimension (`foldlWithin`, `foldlWithin'`, etc.)+* Addition of `ifoldMono` and `ifoldSemi`, thus fixing:+  [#54](https://github.com/lehins/massiv/issues/54)+* Improvement over manipulating index dimensions with addition of type level `Dimension n` data type+  and functions like `getDimension`, `dropDimension`.+* Addition of `insertDim` and type level `insertDimension` as well as `pullOutDim` and+  `pullOutDimension`+* Add partial `extractFromTo'`++# 0.2.3++* Addition of `Profunctor` functions for `Stencil`: `lmapStencil`, `rmapStencil` and `bimapStencil`+* Addition of integration approximation: `Data.Massiv.Array.Numeric.Integral`+* Removed overlapping instances for `DW` in favor of concrete instances.+* Relaxed contraint restrictions on matrix multiplication `(|*|)` and slighly improved performance+  with rewrite rules to avoid double transform.++# 0.2.2++* Addition of `withMArray`, `withMArrayST`.+* Improved preformance of matrix multiplication++# 0.2.1++* Addition of `Stride` and related functions `computeWithStride` and `computeWithStrideAs`.+* Addition of `Window`+* Addition of `loadArray` adn `loadArrayWithStride` with default implementations that will become+  new loading functions in a subsequent release. `loadArray` will replace `loadS` and `loadP`, which+  will be deprecated in the next release and removed in the next major release. Some of this is+  discussed in [#41](https://github.com/lehins/massiv/issues/41)+* Addition of various conversion functions:++  * `fromByteString`, `toByteString` and `toBuilder`+  * `unwrapArray`, `evalArray`, `unwrapMutableArray`, `evalMutableArray`+  * `unwrapNormalFormArray`, `evalNormalFormArray`, `unwrapNormalFormMutableArray`,+    `evalNormalFormMutableArray`++* Fix: `Eq` instance for `Array M ix e`++# 0.2.0++* Fixed type signatures for `convertAs` and `convertProxy`+* Added type constructors for `DW` and `DI`+* `Show` instance for `DW` arrays.+* Addition of `unsafeBackpermuteDW`.+* Breaking changes:+  * Create new `Data.Massiv.Array.Stencil.Unsafe` module and move `forStencilUnsafe` into it.+  * Rename of rank -> dimensions #25+    * Removal `Eq` and `Ord` instances for `Value` #19+    * Move border resolution to `mapStencil` from `makeStencil`.+  * Updated iterators `iterM`, `iterM_`, etc. to have a separate step per dimension.++# 0.1.6++* `Semigroup` and `Monoid` instance for `Value`.+* Addition of `forStencilUnsafe`.+* Fix `minimum` behaving as `maximum`.+* Addition of `foldSemi`.++# 0.1.5++* Fix inverted stencil index calculation [#12](https://github.com/lehins/massiv/issues/12)+* Add support for cross-correlation.++# 0.1.4++* Addition of Monoidal folding `foldMono`.+* Expose `liftArray2`.++# 0.1.3++* Addition of `withPtr` and `unsafeWithPtr` for Storable arrays+* Addition of `computeInto`.+* Exposed `makeWindowedArray`.++# 0.1.2++* Support for GHC-8.4 - instance of `Comp` for `Semigroup`+* Brought back support for GHC-7.10++# 0.1.1++* Addition of experimental `mapM`, `imapM`, `forM`, `iforM`, `generateM` and `generateLinearM`+  functions. Fixes #5+* Addition of `Ord` instances for some array representations.++# 0.1.0++* Initial Release
massiv.cabal view
@@ -1,5 +1,5 @@ name:                massiv-version:             0.3.1.0+version:             0.3.2.0 synopsis:            Massiv (Массив) is an Array Library. description:         Multi-dimensional Arrays with fusion, stencils and parallel computation. homepage:            https://github.com/lehins/massiv@@ -11,6 +11,7 @@ category:            Data, Data Structures, Parallelism build-type:          Custom extra-source-files:  README.md+                   , CHANGELOG.md cabal-version:       >=1.10  flag unsafe-checks@@ -32,6 +33,7 @@                      , Data.Massiv.Array.Manifest                      , Data.Massiv.Array.Manifest.Vector                      , Data.Massiv.Array.Mutable+                     , Data.Massiv.Array.Mutable.Algorithms                      , Data.Massiv.Array.Mutable.Atomic                      , Data.Massiv.Array.Numeric                      , Data.Massiv.Array.Numeric.Integral@@ -56,6 +58,7 @@                      , Data.Massiv.Array.Ops.Fold.Internal                      , Data.Massiv.Array.Ops.Map                      , Data.Massiv.Array.Ops.Slice+                     , Data.Massiv.Array.Ops.Sort                      , Data.Massiv.Array.Ops.Transform                      , Data.Massiv.Array.Stencil.Convolution                      , Data.Massiv.Array.Stencil.Internal@@ -103,6 +106,7 @@                     , Data.Massiv.Array.Ops.ConstructSpec                     , Data.Massiv.Array.Ops.FoldSpec                     , Data.Massiv.Array.Ops.SliceSpec+                    , Data.Massiv.Array.Ops.SortSpec                     , Data.Massiv.Array.Ops.TransformSpec                     , Data.Massiv.Array.Ops.MapSpec                     , Data.Massiv.Array.StencilSpec
src/Data/Massiv/Array.hs view
@@ -118,6 +118,8 @@   , module Data.Massiv.Array.Ops.Transform   -- * Slicing   , module Data.Massiv.Array.Ops.Slice+  -- * Sorting+  , quicksort   -- * Conversion   , module Data.Massiv.Array.Manifest.List   -- * Mutable@@ -143,6 +145,7 @@ import Data.Massiv.Array.Ops.Fold import Data.Massiv.Array.Ops.Map import Data.Massiv.Array.Ops.Slice+import Data.Massiv.Array.Ops.Sort (quicksort) import Data.Massiv.Array.Ops.Transform import Data.Massiv.Array.Stencil import Data.Massiv.Core
src/Data/Massiv/Array/Mutable.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-}@@ -23,7 +24,7 @@   , modify'   , swap   , swap'-  -- ** Operate over `MArray`+  -- ** Operations on @MArray@   -- *** Immutable conversion   , new   , thaw@@ -62,6 +63,7 @@   , iforLinearPrimM_   -- *** Modify   , withMArray+  , withMArrayS   , withMArrayST   -- *** Initialize   , initialize@@ -75,9 +77,11 @@   , loadArrayS   ) where -import Control.Scheduler+-- TODO: add fromListM, et al.+ import Control.Monad (unless) import Control.Monad.ST+import Control.Scheduler import Data.Massiv.Core.Common import Prelude hiding (mapM, read) @@ -677,7 +681,9 @@           return acc' {-# INLINE unfoldlPrimM #-} -+--TODO: in 0.4.0:+--  * forPrimM_  does not modify each element, but simply iterates over+--  * forPrimM - does what forPrimM_ does now. -- | Sequentially loop over a mutable array while modifying each element with an action. -- -- @since 0.3.0@@ -704,11 +710,11 @@ iforLinearPrimM_ marr f = loopM_ 0 (< totalElem (msize marr)) (+ 1) (unsafeLinearModify marr f) {-# INLINE iforLinearPrimM_ #-} -+-- FIXME: supply Scheduler instead of numWorkers and schedule action -- | Create a copy of a pure array, mutate it in place and return its frozen version. The big -- difference between `withMArrayS` is that it's not only gonna respect the computation strategy--- supplied to it, but it will also pass extra argumens to the action that suppose to modify the--- mutable copy of the source array. These two extra arguments are:+-- supplied to it while making a copy, but it will also pass extra argumens to the action that+-- suppose to modify the mutable copy of the source array. These two extra arguments are: -- -- * Number of capabilities derived from the `Comp`utation strategy of the array. --@@ -735,7 +741,7 @@ -- benefit over doing a manual `thawS` followed by a `freezeS` is that an array will be only copied -- once. ----- @since 0.3.0+-- @since 0.3.2 withMArrayS ::      (Mutable r ix e, PrimMonad m)   => Array r ix e@@ -762,6 +768,8 @@   -- | /O(1)/ - Lookup an element in the mutable array. Returns `Nothing` when index is out of bounds.+--+-- @since 0.1.0 read :: (Mutable r ix e, PrimMonad m) =>         MArray (PrimState m) r ix e -> ix -> m (Maybe e) read marr ix =@@ -771,14 +779,14 @@ {-# INLINE read #-}  --- | /O(1)/ - Same as `read`, but lives in IO and throws `IndexOutOfBoundsException` on invalid--- index.-read' :: (Mutable r ix e, MonadThrow m, PrimMonad m) => MArray (PrimState m) r ix e -> ix -> m e-read' marr ix = do-  mval <- read marr ix-  case mval of-    Just e  -> pure e-    Nothing -> throwM $ IndexOutOfBoundsException (msize marr) ix+-- | /O(1)/ - Same as `read`, but throws `IndexOutOfBoundsException` on an invalid index.+--+-- @since 0.1.0+read' :: (Mutable r ix e, PrimMonad m) => MArray (PrimState m) r ix e -> ix -> m e+read' marr ix =+  read marr ix >>= \case+    Just e -> pure e+    Nothing -> throw $ IndexOutOfBoundsException (msize marr) ix {-# INLINE read' #-}  @@ -787,21 +795,25 @@ write :: (Mutable r ix e, PrimMonad m) => MArray (PrimState m) r ix e -> ix -> e -> m Bool write marr ix e =   if isSafeIndex (msize marr) ix-  then unsafeWrite marr ix e >> return True-  else return False+  then unsafeWrite marr ix e >> pure True+  else pure False {-# INLINE write #-}   -- | /O(1)/ - Same as `write`, but lives in IO and throws `IndexOutOfBoundsException` on invalid -- index.+--+-- @since 0.1.0 write' ::-     (Mutable r ix e, MonadThrow m, PrimMonad m) => MArray (PrimState m) r ix e -> ix -> e -> m ()-write' marr ix e = write marr ix e >>= (`unless` throwM (IndexOutOfBoundsException (msize marr) ix))+     (Mutable r ix e, PrimMonad m) => MArray (PrimState m) r ix e -> ix -> e -> m ()+write' marr ix e = write marr ix e >>= (`unless` throw (IndexOutOfBoundsException (msize marr) ix)) {-# INLINE write' #-} -+-- TODO: switch to `... -> m (Maybe e)` -- | /O(1)/ - Modify an element in the cell of a mutable array with a supplied function. Returns -- `False` when index is out of bounds.+--+-- @since 0.1.0 modify :: (Mutable r ix e, PrimMonad m) => MArray (PrimState m) r ix e -> (e -> e) -> ix -> m Bool modify marr f ix =   if isSafeIndex (msize marr) ix@@ -814,15 +826,19 @@   -- | /O(1)/ - Same as `modify`, but throws an error if index is out of bounds.-modify' :: (Mutable r ix e, MonadThrow m, PrimMonad m) =>+--+-- @since 0.1.0+modify' :: (Mutable r ix e, PrimMonad m) =>         MArray (PrimState m) r ix e -> (e -> e) -> ix -> m () modify' marr f ix =-  modify marr f ix >>= (`unless` throwM (IndexOutOfBoundsException (msize marr) ix))+  modify marr f ix >>= (`unless` throw (IndexOutOfBoundsException (msize marr) ix)) {-# INLINE modify' #-}   -- | /O(1)/ - Swap two elements in a mutable array by supplying their indices. Returns `False` when -- either one of the indices is out of bounds.+--+-- @since 0.1.0 swap :: (Mutable r ix e, PrimMonad m) => MArray (PrimState m) r ix e -> ix -> ix -> m Bool swap marr ix1 ix2 = do   let sz = msize marr@@ -837,12 +853,13 @@   -- | /O(1)/ - Same as `swap`, but throws an `IndexOutOfBoundsException` on invalid indices.+--+-- @since 0.1.0 swap' ::-     (Mutable r ix e, MonadThrow m, PrimMonad m) => MArray (PrimState m) r ix e -> ix -> ix -> m ()+     (Mutable r ix e, PrimMonad m) => MArray (PrimState m) r ix e -> ix -> ix -> m () swap' marr ix1 ix2 =   swap marr ix1 ix2 >>=     (`unless` if isSafeIndex (msize marr) ix1-                then throwM $ IndexOutOfBoundsException (msize marr) ix2-                else throwM $ IndexOutOfBoundsException (msize marr) ix1)+                then throw $ IndexOutOfBoundsException (msize marr) ix2+                else throw $ IndexOutOfBoundsException (msize marr) ix1) {-# INLINE swap' #-}-
+ src/Data/Massiv/Array/Mutable/Algorithms.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE ExplicitForAll #-}+{-# LANGUAGE FlexibleContexts #-}+-- |+-- Module      : Data.Massiv.Array.Mutable.Algorithms+-- Copyright   : (c) Alexey Kuleshevich 2019+-- License     : BSD3+-- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>+-- Stability   : experimental+-- Portability : non-portable+--+module Data.Massiv.Array.Mutable.Algorithms+  ( quicksortM_+  , unstablePartitionM+  ) where++import Data.Massiv.Array.Ops.Sort+import Data.Massiv.Core.Common+++-- | Partition elements of the supplied mutable vector according to the predicate.+--+-- ==== __Example__+--+-- >>> import Data.Massiv.Array as A+-- >>> import Data.Massiv.Array.Mutable.Algorithms+-- >>> m <- thaw ([2,1,50,10,20,8] :: Array P Ix1 Int)+-- >>> unstablePartitionM m (<= 10)+-- 4+-- >>> freeze Seq m+-- Array P Seq (Sz1 6)+--   [ 2, 1, 8, 10, 20, 50 ]+--+-- @since 0.3.2+unstablePartitionM ::+     forall r e m. (Mutable r Ix1 e, PrimMonad m)+  => MArray (PrimState m) r Ix1 e+  -> (e -> Bool) -- ^ Predicate+  -> m Ix1+unstablePartitionM marr f = unsafeUnstablePartitionRegionM marr f 0 (unSz (msize marr) - 1)
+ src/Data/Massiv/Array/Ops/Sort.hs view
@@ -0,0 +1,110 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ExplicitForAll #-}+{-# LANGUAGE FlexibleContexts #-}+-- |+-- Module      : Data.Massiv.Array.Ops.Sort+-- Copyright   : (c) Alexey Kuleshevich 2018-2019+-- License     : BSD3+-- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>+-- Stability   : experimental+-- Portability : non-portable+--+module Data.Massiv.Array.Ops.Sort+  ( quicksort+  , quicksortM_+  , unsafeUnstablePartitionRegionM+  ) where++import Control.Monad (when)+import Control.Scheduler+import Data.Massiv.Array.Mutable+import Data.Massiv.Core.Common+import System.IO.Unsafe++-- | Partition a segment of a vector. Starting and ending indices are unchecked.+--+-- @since 0.3.2+unsafeUnstablePartitionRegionM ::+     forall r e m. (Mutable r Ix1 e, PrimMonad m)+  => MArray (PrimState m) r Ix1 e+  -> (e -> Bool)+  -> Ix1 -- ^ Start index of the region+  -> Ix1 -- ^ End index of the region+  -> m Ix1+unsafeUnstablePartitionRegionM marr f start end = fromLeft start (end + 1)+  where+    fromLeft i j+      | i == j = pure i+      | otherwise = do+        x <- unsafeRead marr i+        if f x+          then fromLeft (i + 1) j+          else fromRight i (j - 1)+    fromRight i j+      | i == j = pure i+      | otherwise = do+        x <- unsafeRead marr j+        if f x+          then do+            unsafeWrite marr j =<< unsafeRead marr i+            unsafeWrite marr i x+            fromLeft (i + 1) j+          else fromRight i (j - 1)+{-# INLINE unsafeUnstablePartitionRegionM #-}+++-- | This is an implementation of [Quicksort](https://en.wikipedia.org/wiki/Quicksort), which is an+-- efficient, but unstable sort that uses Median-of-three for pivot choosing, as such it performs+-- very well not only for random values, but also for common edge cases like already sorted,+-- reversed sorted and arrays with many duplicate elements. It will also respect the computation+-- strategy and will result in a nice speed up for systems with multiple CPUs.+--+-- @since 0.3.2+quicksort ::+     (Mutable r Ix1 e, Ord e) => Array r Ix1 e -> Array r Ix1 e+quicksort arr =+  unsafePerformIO $+  withMArray arr (\n s -> quicksortM_ (trivialScheduler_ {numWorkers = n, scheduleWork = s}))+{-# INLINE quicksort #-}++-- | Mutable version of `quicksort`+--+-- @since 0.3.2+quicksortM_ ::+     (Ord e, Mutable r Ix1 e, PrimMonad m)+  => Scheduler m ()+  -> MArray (PrimState m) r Ix1 e+  -> m ()+quicksortM_ scheduler marr =+  scheduleWork scheduler $ qsort (numWorkers scheduler) 0 (unSz (msize marr) - 1)+  where+    leSwap i j = do+      ei <- unsafeRead marr i+      ej <- unsafeRead marr j+      if ei < ej+        then do+          unsafeWrite marr i ej+          unsafeWrite marr j ei+          pure ei+        else pure ej+    {-# INLINE leSwap #-}+    getPivot lo hi = do+      let !mid = (hi + lo) `div` 2+      _ <- leSwap mid lo+      _ <- leSwap hi lo+      leSwap mid hi+    {-# INLINE getPivot #-}+    qsort !n !lo !hi =+      when (lo < hi) $ do+        p <- getPivot lo hi+        l <- unsafeUnstablePartitionRegionM marr (< p) lo (hi - 1)+        h <- unsafeUnstablePartitionRegionM marr (== p) l hi+        if n > 0+          then do+            let !n' = n - 1+            scheduleWork scheduler $ qsort n' lo (l - 1)+            scheduleWork scheduler $ qsort n' h hi+          else do+            qsort n lo (l - 1)+            qsort n h hi+{-# INLINE quicksortM_ #-}
src/Data/Massiv/Array/Unsafe.hs view
@@ -61,6 +61,8 @@   , unsafeAtomicOrIntArray   , unsafeAtomicXorIntArray   , unsafeCasIntArray+    -- ** Other operations+  , unsafeUnstablePartitionRegionM   ) where  import Data.Massiv.Array.Delayed.Pull (D)@@ -70,6 +72,7 @@ import Data.Massiv.Core.Common import Data.Massiv.Core.Index.Internal (Sz(SafeSz)) import Data.Massiv.Core.Index.Stride (Stride(SafeStride))+import Data.Massiv.Array.Ops.Sort (unsafeUnstablePartitionRegionM)  unsafeBackpermute :: (Source r' ix' e, Index ix) =>                      Sz ix -> (ix -> ix') -> Array r' ix' e -> Array D ix e
+ tests/Data/Massiv/Array/Ops/SortSpec.hs view
@@ -0,0 +1,17 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeApplications #-}+module Data.Massiv.Array.Ops.SortSpec (spec) where++import Data.List as L+import Data.Massiv.CoreArbitrary as A+++prop_IsSorted :: (b -> b) -> ([Int] -> b) -> (b -> [Int]) -> [Int] -> Property+prop_IsSorted sortWith from to xs =+  to (sortWith (from xs)) === sort xs++spec :: Spec+spec =+  describe "QuickSort" $ do+    it "Seq" $ property $ prop_IsSorted (quicksort @P) (A.fromList Seq) A.toList+    it "Par" $ property $ prop_IsSorted (quicksort @P) (A.fromList (ParN 4)) A.toList
tests/Data/Massiv/Array/Ops/TransformSpec.hs view
@@ -69,6 +69,22 @@   describe "Sequence" $ do     it "ConsSnoc" $ property prop_ConsSnoc     it "UnconsUnsnoc" $ property prop_UnconsUnsnoc+  describe "zoomWithGrid" $ do+    it "Ix1" $ property (prop_zoomWithGridStrideCompute @Ix1)+    it "Ix2" $ property (prop_zoomWithGridStrideCompute @Ix2)+    it "Ix3" $ property (prop_zoomWithGridStrideCompute @Ix3)+    it "Ix4" $ property (prop_zoomWithGridStrideCompute @Ix4)++prop_zoomWithGridStrideCompute :: (Show (Array P ix Int), Index ix) => Array D ix Int -> Stride ix -> Int -> Property+prop_zoomWithGridStrideCompute arr stride defVal =+  (computeWithStrideAs P stride' arr' ===+   A.replicate Seq (Sz (liftIndex (+ 1) $ unSz (size arr))) defVal) .&&.+  (computeWithStrideAs P stride' (extract' (pureIndex 1) sz' arr') === compute arr)+  where+    arr' = computeAs P (zoomWithGrid defVal stride arr)+    sz' = Sz (liftIndex (subtract 1) $ unSz (size arr'))+    stride' = Stride (liftIndex (+ 1) $ unStride stride)+  prop_UnconsUnsnoc :: Array D Ix1 Int -> Bool -> Property prop_UnconsUnsnoc arr unconsFirst =