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 +185/−0
- massiv.cabal +5/−1
- src/Data/Massiv/Array.hs +3/−0
- src/Data/Massiv/Array/Mutable.hs +43/−26
- src/Data/Massiv/Array/Mutable/Algorithms.hs +39/−0
- src/Data/Massiv/Array/Ops/Sort.hs +110/−0
- src/Data/Massiv/Array/Unsafe.hs +3/−0
- tests/Data/Massiv/Array/Ops/SortSpec.hs +17/−0
- tests/Data/Massiv/Array/Ops/TransformSpec.hs +16/−0
+ 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 =