Handy synonym for rangeInclusive Seq. Similar to .. for list.
Ix1 4 ... 10Array D Seq (Sz1 7) [ 4, 5, 6, 7, 8, 9, 10 ]
:: a typeCtrl KGHC 10.0.0.20260917 · lts/ghc-10.0.x · 8c2f8e8 · 2026-10-19
Modulemassiv-1.0.5.0Haskell2010
Massiv is a library, that allows creation and manipulation of arrays in parallel and
sequentially. Depending on the representation (r), an Array r ix e will have
certain properties that are unique to that particular representation, but all of them will share
the same trait, that an array is simply a mapping from an index (ix) of an arbitrary
dimension to an element (e) of some value. Which means that some representations describe
classic arrays and are backed by a contiguous chunk of memory reserved for the elements (or
pointers to elements), namely arrays with Manifest representations:
B - The most basic type of array that can hold any type of element in a boxed form, i.e. each element is a pointer to the actual value, therefore it is also the slowest representation. Elements are kept in a Weak Head Normal Form (WHNF).
BN - Similar to B, it is also a boxed type, except its elements are always kept in a Normal Form (NF). This property is very useful for parallel processing, i.e. when calling compute you do want all of your elements to be fully evaluated.
BL - Similar to B, it is also a boxed type, but lazy. Its elements are not evaluated when array is computed.
S - Is a type of array that is backed by pinned memory, therefore pointers to those arrays can be passed to FFI calls, because Garbage Collector (GC) is guaranteed not to move it. Elements must be an instance of Storable class. It is just as efficient as P and U arrays, except it is subject to fragmentation.
U - Unboxed representation. Elements must be an instance of Unbox class.
P - Array that can hold Haskell primitives, such as Int, Word, Double, etc. Any element must be an instance of Prim class.
There are also array representations that only describe how values for its elements can be computed or loaded into memory, as such, they are represented by functions and do not impose the memory overhead, that is normally associated with arrays. They are needed for proper fusion and parallelization of computation.
D - delayed array that is a mere function from an index to an element. Also known as Pull array. Crucial representation for fusing computation. Use computeAs in order to load array into Manifest representation.
DL - delayed load array representation that describes how an array can be loaded. Also known as Push array. Useful for fusing various array combining functions. Use computeAs in order to load array into Manifest representation.
DS - delayed stream vector representation that describes how to handle a vector with possibility of unknown length. Useful for filtering and unfolding. Use computeAs in order to load such vector into Manifest representation.
DI - delayed interleaved array. Same as D, but performs better with unbalanced computation, when evaluation of one element takes much longer than of its neighbor.
DW - delayed windowed array. This peculiar representation allows for very fast Stencil computation.
Other Array types:
L - this type isn't particularly useful on its own, but because it has unique ability to be converted to and from nested lists in constant time, it provides a perfect intermediary for conversion of nested lists into manifest arrays.
Most of the Manifest arrays are capable of in-place mutation. Check out Data.Massiv.Array.Mutable module for available functionality.
Many of the function names exported by this package will clash with the ones from Prelude, hence it can be more convenient to import like this:
import Prelude as P
import Data.Massiv.Array as A
Handy synonym for rangeInclusive Seq. Similar to .. for list.
Ix1 4 ... 10Array D Seq (Sz1 7) [ 4, 5, 6, 7, 8, 9, 10 ]
enumFromN Same as enumFromStepN with step dx = 1.
Related: senumFromN, senumFromStepN, enumFromStepN, rangeSize, rangeStepSize, range
import Data.Massiv.ArrayenumFromN Seq (5 :: Double) 3Array D Seq (Sz1 3) [ 5.0, 6.0, 7.0 ]
Similar:
enumFromStepN Enumerate from a starting number x exactly n times with a custom step value
dx. Unlike senumFromStepN, there is no dependency on neigboring
elements therefore enumFromStepN is parallelizable.
Related: senumFromN, senumFromStepN, enumFromN, rangeSize, rangeStepSize, range, rangeStepM
import Data.Massiv.ArrayenumFromStepN Seq 1 (0.1 :: Double) 5Array D Seq (Sz1 5) [ 1.0, 1.1, 1.2, 1.3, 1.4 ]enumFromStepN Seq (-pi :: Float) (pi/4) 9Array D Seq (Sz1 9) [ -3.1415927, -2.3561945, -1.5707964, -0.78539824, 0.0, 0.78539824, 1.5707963, 2.3561947, 3.1415927 ]
Similar:
Prelude.enumFromSimilar to
take n [x, x + dx ..]
, except that
is parallelizable and it only works for
and not for
elements. Floating point value will be slightly different as well.
Data.Vector.Generic.enumFromStepNSimilar in the outcome, but very different in the way it works.
Similar to expandWithin, except it uses the innermost dimension.
Similar to expandWithin, except it uses the outermost dimension.
Function that expands an array to one with a higher dimension.
This is useful for constructing arrays where there is shared computation between multiple cells. The makeArray method of constructing arrays:
makeArray :: Construct r ix e => Comp -> ix -> (ix -> e) -> Array r ix e...runs a function ix -> e at every array index. This is inefficient if
there is a substantial amount of repeated computation that could be shared
while constructing elements on the same dimension. The expand functions make
this possible. First you construct an Array r (Lower ix) a of one fewer
dimensions where a is something like Array r Ix1 a or Array r Ix2 a. Then
you use expandWithin and a creation function a -> Int -> b to create an
Array D Ix2 b or Array D Ix3 b respectfully.
import Data.Massiv.Arraya = makeArrayR U Seq (Sz1 6) (+10) -- Imagine (+10) is some expensive functionaArray U Seq (Sz1 6) [ 10, 11, 12, 13, 14, 15 ]expandWithin Dim1 5 (\ e j -> (j + 1) * 100 + e) a :: Array D Ix2 IntArray D Seq (Sz (6 :. 5)) [ [ 110, 210, 310, 410, 510 ] , [ 111, 211, 311, 411, 511 ] , [ 112, 212, 312, 412, 512 ] , [ 113, 213, 313, 413, 513 ] , [ 114, 214, 314, 414, 514 ] , [ 115, 215, 315, 415, 515 ] ]expandWithin Dim2 5 (\ e j -> (j + 1) * 100 + e) a :: Array D Ix2 IntArray D Seq (Sz (5 :. 6)) [ [ 110, 111, 112, 113, 114, 115 ] , [ 210, 211, 212, 213, 214, 215 ] , [ 310, 311, 312, 313, 314, 315 ] , [ 410, 411, 412, 413, 414, 415 ] , [ 510, 511, 512, 513, 514, 515 ] ]
Similar to expandWithin, except that dimension is specified at a value level, which means it will throw an exception on an invalid dimension.
Similar to expandWithin, except that dimension is specified at a value level, which means it will throw an exception on an invalid dimension.
Same as iterateN, but with index aware function.
Sequentially iterate over each cell in the array in the row-major order while continuously aplying the accumulator at each step.
import Data.Massiv.ArrayiterateN (Sz2 2 10) succ (10 :: Int)Array DL Seq (Sz (2 :. 10)) [ [ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ] , [ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 ] ]
Unfold sequentially from the right with an index aware function.
Right unfold of a delayed load array with index aware function
Similar to makeArray, but construct the array sequentially using an Applicative interface.
Note - using generateArray or generateArrayS will always be faster, althought not always possible.
Same as makeArrayA, but with ability to supply result array representation.
Same as makeArrayA, but with linear index.
Same as makeArrayLinear, but with ability to supply resulting representation
Just like makeArray but with ability to specify the result representation as an
argument. Note the Data.Massiv.Array.Unboxed type constructor in the below example.
import Data.Massiv.ArraymakeArrayR U Par (Sz (2 :> 3 :. 4)) (\ (i :> j :. k) -> i * i + j * j == k * k)Array U Par (Sz (2 :> 3 :. 4)) [ [ [ True, False, False, False ] , [ False, True, False, False ] , [ False, False, True, False ] ] , [ [ False, True, False, False ] , [ False, False, False, False ] , [ False, False, False, False ] ] ]
makeSplitSeedArray :: (Iterator it, Index ix)=> itIterator
-> gInitial seed
-> (g -> (g, g))A function that can split a seed into two independent seeds. It will be called the same number of times as the number of jobs that will get scheduled during parallelization. Eg. only once for the sequential case.
-> CompComputation strategy.
-> Sz ixResulting size of the array.
-> (Ix1 -> ix -> g -> (e, g))A function that produces a value and the next seed. It takes both versions of the index, in linear and in multi-dimensional forms, as well as the current seeding value.
-> Array DL ix eCreate a delayed array with an initial seed and a splitting function. It is
somewhat similar to iunfoldlS_ function, but it is capable of parallelizing
computation and iterating over the array accoriding to the supplied
Iterator. Upon parallelization every job will get the second part of the
result produced by the split function, while the first part will be used for
subsequent splits. This function is similar to
Data.Massiv.Array.Manifest.generateSplitSeedArray
Same as makeArrayR, but restricted to 1-dimensional arrays.
randomArray :: Index ix=> gInitial random value generator
-> (g -> (g, g))A function that can split a generator into two independent generators. It will only be called if supplied computation strategy needs more than one worker threads.
-> (g -> (e, g))A function that produces a random value and the next generator
-> CompComputation strategy.
-> Sz ixResulting size of the array.
-> Array DL ix eCreate an array with random values by using a pure splittable random number generator such as one provided by either splitmix or random packages. If you don't have a splittable generator consider using randomArrayS or randomArrayWS instead.
Because of the pure nature of the generator and its splitability we are not only able to parallelize the random value generation, but also guarantee that it will be deterministic, granted none of the arguments have changed.
Note: Starting with massiv-1.1.0 this function will be deprecated in
favor of a more general genSplitArray
import Data.Massiv.Arrayimport System.Random.SplitMix as SplitMixgen = SplitMix.mkSMGen 217randomArray gen SplitMix.splitSMGen SplitMix.nextDouble (ParN 2) (Sz2 2 3) :: Array DL Ix2 DoubleArray DL (ParN 2) (Sz (2 :. 3)) [ [ 0.7383156058619669, 0.39904053166835896, 0.5617584038393628 ] , [ 0.7218718218678238, 0.7006722805067258, 0.7225894731396042 ] ]
import Data.Massiv.Arrayimport System.Random as Randomgen = Random.mkStdGen 217randomArray gen Random.split Random.random (ParN 2) (Sz2 2 3) :: Array DL Ix2 DoubleArray DL (ParN 2) (Sz (2 :. 3)) [ [ 0.2616843941380331, 0.600959468331641, 0.4382415961606372 ] , [ 0.27812817813217605, 0.2993277194932741, 0.2774105268603957 ] ]
randomArrayS Similar to randomArray but performs generation sequentially, which means it doesn't require splitability property. Another consequence is that it returns the new generator together with manifest array of random values.
import Data.Massiv.Arrayimport System.Random.SplitMix as SplitMixgen = SplitMix.mkSMGen 217snd $ randomArrayS gen (Sz2 2 3) SplitMix.nextDouble :: Array P Ix2 DoubleArray P Seq (Sz (2 :. 3)) [ [ 0.8878273949359751, 0.11290807610140963, 0.7383156058619669 ] , [ 0.39904053166835896, 0.5617584038393628, 0.16248374266020216 ] ]
import Data.Massiv.Arrayimport System.Random.Mersenne.Pure64 as MTgen = MT.pureMT 217snd $ randomArrayS gen (Sz2 2 3) MT.randomDouble :: Array P Ix2 DoubleArray P Seq (Sz (2 :. 3)) [ [ 0.5504018416543631, 0.22504666452851707, 0.4480480867867128 ] , [ 0.7139711572975297, 0.49401087853770953, 0.9397201599368645 ] ]
import Data.Massiv.Arrayimport System.Random as Systemgen = System.mkStdGen 217snd $ randomArrayS gen (Sz2 2 3) System.random :: Array P Ix2 DoubleArray P Seq (Sz (2 :. 3)) [ [ 0.11217260506402493, 0.8870919238985904, 0.2616843941380331 ] , [ 0.600959468331641, 0.4382415961606372, 0.8375162573397977 ] ]
randomArrayWS :: (Manifest r e, Index ix, MonadUnliftIO m, PrimMonad m)=> WorkerStates gUse initWorkerStates to initialize you per thread generators
-> Sz ixResulting size of the array
-> (g -> m e)Generate the value using the per thread generator.
-> m (Array r ix e)This is a stateful approach of generating random values. If your generator is pure and splittable, it is better to use randomArray instead, which will give you a pure, deterministic and parallelizable generation of arrays. On the other hand, if your generator is not thread safe, which is most likely the case, instead of using some sort of global mutex, WorkerStates allows you to keep track of individual state per worker (thread), which fits parallelization of random value generation perfectly. All that needs to be done is generators need to be initialized once per worker and then they can be reused as many times as necessary.
In the example below we take a stateful random number generator from wmc-random, which is not thread safe, and safely parallelize it by giving each thread it's own generator. There is a caveat of course, statistical independence will depend on the entropy in your initial seeds, so do not use the example below verbatim, since initial seeds are sequential numbers.
import Data.Massiv.Array as Aimport System.Random.MWC as MWC (initialize)import System.Random.Stateful (uniformRM)import Control.Scheduler (initWorkerStates, getWorkerId):set -XTypeApplicationsgens <- initWorkerStates Par (MWC.initialize . A.toPrimitiveVector . A.singleton @P @Ix1 . fromIntegral . getWorkerId)randomArrayWS gens (Sz2 2 3) (uniformRM (0, 9)) :: IO (Matrix P Double)Array P Par (Sz (2 :. 3)) [ [ 8.999240522095299, 6.832223390653755, 3.065728078741671 ] , [ 7.242581103346686, 2.4565807301968623, 0.4514262066689775 ] ]randomArrayWS gens (Sz1 6) (uniformRM (0, 9)) :: IO (Vector P Int)Array P Par (Sz1 6) [ 8, 8, 7, 1, 1, 2 ]
Create an array of indices with a range from start to finish (not-including), where indices are incremeted by one.
import Data.Massiv.Arrayrange Seq (Ix1 1) 6Array D Seq (Sz1 5) [ 1, 2, 3, 4, 5 ]fromIx2 <$> range Seq (-1) (2 :. 2)Array D Seq (Sz (3 :. 3)) [ [ (-1,-1), (-1,0), (-1,1) ] , [ (0,-1), (0,0), (0,1) ] , [ (1,-1), (1,0), (1,1) ] ]
Just like range, except the finish index is included.
rangeSize Create an array of specified size with indices starting with some index at position 0 and
incremented by 1 until the end of the array is reached
Same as rangeStepM, but will throw an error whenever step contains zeros.
import Data.Massiv.ArrayrangeStep' Seq (Ix1 1) 2 6Array D Seq (Sz1 3) [ 1, 3, 5 ]
Just like range, except the finish index is included.
Just like rangeStepM, except the finish index is included.
rangeStepM :: (Index ix, MonadThrow m)=> CompComputation strategy
-> ixStart
-> ixStep. Negative and positive values are ok, but can't have zeros
-> ixEnd
-> m (Array D ix ix)Same as range, but with a custom step.
Throws Exceptions: IndexZeroException
import Data.Massiv.ArrayrangeStepM Seq (Ix1 1) 2 8Array D Seq (Sz1 4) [ 1, 3, 5, 7 ]rangeStepM Seq (Ix1 1) 0 8*** Exception: IndexZeroException: 0
rangeStepSize Same as rangeSize, but with ability to specify the step.
Unfold sequentially from the end. There is no way to save the accumulator after unfolding is done, since resulting array is delayed, but it's possible to use unfoldlPrimM to achieve such effect.
Right unfold into a delayed load array. For the opposite direction use unfoldlS_.
import Data.Massiv.ArrayunfoldrS_ (Sz1 10) (\xs -> (Prelude.head xs, Prelude.tail xs)) ([10 ..] :: [Int])Array DL Seq (Sz1 10) [ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 ]
uniformArray Generate a random array where all elements are sampled from a uniform distribution.
uniformRangeArray Same as uniformArray, but will generate values in a supplied range.
Create an Array with no elements. By itself it is not particularly useful, but it serves as a nice base for constructing larger arrays.
import Data.Massiv.Array as A:set -XTypeApplicationsxs = empty @DL @Ix1 @Doublesnoc (cons 4 (cons 5 xs)) 22Array DL Seq (Sz1 3) [ 4.0, 5.0, 22.0 ]
Create an Array with a single element.
import Data.Massiv.Array as Asingleton 7 :: Array D Ix4 DoubleArray D Seq (Sz (1 :> 1 :> 1 :. 1)) [ [ [ [ 7.0 ] ] ] ]
Instead of specifying type signature we could use TypeApplications
:set -XTypeApplicationssingleton @U @Ix4 @Double 7Array U Seq (Sz (1 :> 1 :> 1 :. 1)) [ [ [ [ 7.0 ] ] ] ]
Construct an Array. Resulting type either has to be unambiguously inferred or restricted manually, like in the example below. Use "Data.Massiv.Array.makeArrayR" if you'd like to specify representation as an argument.
import Data.Massiv.ArraymakeArray Seq (Sz (3 :. 4)) (\ (i :. j) -> if i == j then i else 0) :: Array D Ix2 IntArray D Seq (Sz (3 :. 4)) [ [ 0, 0, 0, 0 ] , [ 0, 1, 0, 0 ] , [ 0, 0, 2, 0 ] ]
Instead of restricting the full type manually we can use TypeApplications as convenience:
:set -XTypeApplicationsmakeArray @P @_ @Double Seq (Sz2 3 4) $ \(i :. j) -> logBase (fromIntegral i) (fromIntegral j)Array P Seq (Sz (3 :. 4)) [ [ NaN, -0.0, -0.0, -0.0 ] , [ -Infinity, NaN, Infinity, Infinity ] , [ -Infinity, 0.0, 1.0, 1.5849625007211563 ] ]
Same as makeArray, but produce elements using linear row-major index.
import Data.Massiv.ArraymakeArrayLinear Seq (Sz (2 :. 4)) id :: Array D Ix2 IntArray D Seq (Sz (2 :. 4)) [ [ 0, 1, 2, 3 ] , [ 4, 5, 6, 7 ] ]
Construct an array of the specified size that contains the same element in all of the cells.
Get computation strategy of this array
Set computation strategy for this array
:set -XTypeApplicationsimport Data.Massiv.Arraya = singleton @DL @Ix1 @Int 0aArray DL Seq (Sz1 1) [ 0 ]setComp (ParN 6) a -- use 6 capabilitiesArray DL (ParN 6) (Sz1 1) [ 0 ]
Compute array sequentially disregarding predefined computation strategy. Very much the same as computePrimM, but executed in ST, thus pure.
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.
Compute an array in PrimMonad sequentially disregarding predefined computation strategy.
Just as compute, but let's you supply resulting representation type as an argument.
import Data.Massiv.ArraycomputeAs P $ range Seq (Ix1 0) 10Array P Seq (Sz1 10) [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
Same as compute and computeAs, but let's you supply resulting representation type as a proxy argument.
Useful only really for cases when representation constructor or TypeApplications extension
aren't desireable for some reason:
import Data.Proxyimport Data.Massiv.ArraycomputeProxy (Proxy :: Proxy P) $ (^ (2 :: Int)) <$> range Seq (Ix1 0) 10Array P Seq (Sz1 10) [ 0, 1, 4, 9, 16, 25, 36, 49, 64, 81 ]
Same as computeWithStride, but with ability to specify resulting array representation.
O(n) - Make an exact immutable copy of an Array.
O(n) - conversion between array types. A full copy will occur, unless when the source and result arrays are of the same representation, in which case it is an O(1) operation.
Same as convert, but let's you supply resulting representation type as an argument.
Convert a ragged array into a common array with rectangular shape. Throws ShapeException whenever supplied ragged array does not have a rectangular shape.
Same as fromRaggedArrayM, but will throw an impure exception if its shape is not rectangular.
module Data.Massiv.Vector
O(1) - Get the exact size of an immutabe array. Most of the time will
produce the size in constant time, except for Data.Massiv.Array.DS
representation, which could result in evaluation of the whole stream. See
maxLinearSize and slength for more info.
O(1) - Get the number of elements in the array.
import Data.Massiv.ArrayelemsCount $ range Seq (Ix1 10) 155
O(1) - Check if array has elements.
import Data.Massiv.ArrayisEmpty (singleton 1 :: Array D Ix2 Int)FalseisEmpty (empty :: Array D Ix2 Int)True
O(1) - Check if array has elements.
import Data.Massiv.ArrayisNotEmpty (singleton 1 :: Array D Ix2 Int)TrueisNotEmpty (empty :: Array D Ix2 Int)False
O(1) - Check whether an array is empty or not.
import Data.Massiv.ArrayisNull $ range Seq (Ix2 10 20) (11 :. 21)FalseisNull $ range Seq (Ix2 10 20) (10 :. 21)TrueisNull (empty :: Array D Ix5 Int)TrueisNull $ sfromList []True
O(1) - Check if array has elements.
import Data.Massiv.ArrayisNotNull (singleton 1 :: Array D Ix2 Int)TrueisNotNull (empty :: Array D Ix2 Int)False
O(1) - Infix version of indexM.
Exceptions: IndexOutOfBoundsException
import Data.Massiv.Array as A:set -XTypeApplicationsa <- fromListsM @U @Ix2 @Int Seq [[1,2,3],[4,5,6]]aArray U Seq (Sz (2 :. 3)) [ [ 1, 2, 3 ] , [ 4, 5, 6 ] ]a !? 0 :. 23a !? 0 :. 3*** Exception: IndexOutOfBoundsException: (0 :. 3) is not safe for (Sz (2 :. 3))a !? 0 :. 3 :: Maybe IntNothing
O(1) - Infix version of index'.
import Data.Massiv.Array as Aa = computeAs U $ iterateN (Sz (2 :. 3)) succ (0 :: Int)aArray U Seq (Sz (2 :. 3)) [ [ 1, 2, 3 ] , [ 4, 5, 6 ] ]a ! 0 :. 23
O(1) - Lookup an element in the array, where array itself is wrapped with MonadThrow. This operator is useful when used together with slicing or other functions that can fail.
Exceptions: IndexOutOfBoundsException
import Data.Massiv.Array as A:set -XTypeApplicationsma = fromListsM @U @Ix3 @Int @Maybe Seq [[[1,2,3]],[[4,5,6]]]maJust (Array U Seq (Sz (2 :> 1 :. 3)) [ [ [ 1, 2, 3 ] ] , [ [ 4, 5, 6 ] ] ])ma ??> 1Just (Array U Seq (Sz (1 :. 3)) [ [ 4, 5, 6 ] ])ma ??> 1 ?? 0 :. 2Just 6ma ?? 1 :> 0 :. 2Just 6
O(1) - Lookup an element in the array.
Exceptions: IndexOutOfBoundsException
O(1) - Lookup an element in the array. This is a partial function and it will throw an error when index is out of bounds. It is safer to use indexM instead.
import Data.Massiv.Array:set -XOverloadedListsxs = [0..100] :: Array U Ix1 Intindex' xs 5050
O(1) - Lookup an element in the array, while using default element when index is out of bounds.
import Data.Massiv.Array:set -XOverloadedListsxs = [0..100] :: Array P Ix1 IntdefaultIndex 999 xs 100100defaultIndex 999 xs 101999
O(1) - Lookup an element in the array. Use a border resolution technique when index is out of bounds.
import Data.Massiv.Array as A:set -XOverloadedListsxs = [0..100] :: Array U Ix1 IntborderIndex Wrap xs <$> range Seq 99 104Array D Seq (Sz1 5) [ 99, 100, 0, 1, 2 ]
This is just like indexM function, but it allows getting values from delayed arrays as well as Manifest. As the name suggests, indexing into a delayed array at the same index multiple times will cause evaluation of the value each time and can destroy the performace if used without care.
import Control.Exceptionimport Data.Massiv.ArrayevaluateM (range Seq (Ix2 10 20) (100 :. 210)) 50 :: Either SomeException Ix2Right (60 :. 70)evaluateM (range Seq (Ix2 10 20) (100 :. 210)) 150 :: Either SomeException Ix2Left (IndexOutOfBoundsException: (150 :. 150) is not safe for (Sz (90 :. 190)))
Similar to evaluateM, but will throw an error on out of bounds indices.
import Data.Massiv.Arrayevaluate' (range Seq (Ix2 10 20) (100 :. 210)) 5060 :. 70
Map an index aware function over an array
Same as mapIO but with arguments flipped.
Same as mapIO_ but with arguments flipped.
This is the same example as in forM_, with important difference that accumulator ref will be
modified concurrently by as many threads as there are capabilities.
import Data.Massiv.Arrayimport Data.IORefref <- newIORef 0 :: IO (IORef Int)forIO_ (range Par (Ix1 0) 1000) $ \ i -> atomicModifyIORef' ref (\v -> (v+i, ()))readIORef ref499500
Same as mapM except with arguments flipped.
Just like mapM_, except with flipped arguments.
Here is a common way of iterating N times using a for loop in an imperative language with mutation being an obvious side effect:
import Data.Massiv.Array as Aimport Data.IORefref <- newIORef 0 :: IO (IORef Int)A.forM_ (range Seq (Ix1 0) 1000) $ \ i -> modifyIORef' ref (+i)readIORef ref499500
Same as iforWS, but without the index.
Same as imapIO but with arguments flipped.
Same as imapIO_ but with arguments flipped.
Same as forM, except with an index aware action.
Just like imapM_, except with flipped arguments.
Same as imapM_, but will use the supplied scheduler.
Same as imapWS, but with source array and mapping action arguments flipped.
Same as mapIO but map an index aware action instead. Respects computation strategy.
Same as mapIO_, but map an index aware action instead.
Map an index aware monadic action over an array sequentially.
Map a monadic index aware function over an array sequentially, while discarding the result.
import Data.Massiv.ArrayimapM_ (curry print) $ range Seq (Ix1 10) 15(0,10)(1,11)(2,12)(3,13)(4,14)
Same as imapM_, but will use the supplied scheduler.
Same as imapIO, but ignores the inner computation strategy and uses stateful workers during computation instead. Use initWorkerStates for the WorkerStates initialization.
iterArrayLinearM_ :: (Load r ix e, MonadPrimBase s m)=> Scheduler s ()-> Array r ix eArray that is being loaded
-> (Int -> e -> m ())Function that writes an element into target array
-> m ()iterArrayLinearWithStrideM_ :: (StrideLoad r ix e, MonadPrimBase s m)=> Scheduler s ()-> Stride ixStride to use
-> Sz ixSize of the target array affected by the stride.
-> Array r ix eArray that is being loaded
-> (Int -> e -> m ())Function that writes an element into target array
-> m ()Traverse with an Applicative index aware action over an array sequentially.
Traverse with an Applicative index aware action over an array sequentially.
Same as traversePrim, but traverse with index aware action.
Just like zipWith, except with an index aware function.
Just like zipWith3, except with an index aware function.
Same as izipWithA, but for three arrays.
Just like zipWith4, except with an index aware function.
Similar to zipWith, except does it sequentially and using the Applicative. Note that resulting array has Manifest representation.
Map a function over an array
mapM Map a monadic action over an array sequentially.
Map a monadic function over an array sequentially, while discarding the result.
import Data.Massiv.Array as ArangeStepM Par (Ix1 10) 12 60 >>= A.mapM_ print1022344658
Same as imapWS, but without the index.
Sequence actions in a source array.
Sequence actions in a source array, while discarding the result.
Traverse with an Applicative action over an array sequentially.
Note - using traversePrim instead will always be significantly faster, roughly about 30 times faster in practice.
Traverse sequentially over a source array, while discarding the result.
Traverse sequentially within PrimMonad over an array with an action.
Unzip two arrays
Unzip three arrays
Unzip four arrays
Zip two arrays
Zip three arrays
Zip four arrays
Zip two arrays with a function. Resulting array will be an intersection of source arrays in case their dimensions do not match.
Just like zipWith, except zip three arrays with a function.
Same as zipWithA, but for three arrays.
Just like zipWith, except zip four arrays with a function.
Similar to zipWith, except does it sequentially and using the Applicative. Note that resulting array has Manifest representation.
All folding is done in a row-major order.
Compute array ordering by applying a comparing function to each element. The exact ordering is unspecified so this is only intended for use in maps and the like where you need an ordering but do not care about which one is used.
Compute array equality by applying a comparing function to each element. Empty arrays are always equal, regardless of their size.
O(n) - Determines whether all elements of the array satisfy a predicate.
O(n) - Compute conjunction of all elements.
O(n) - Determines whether an element is present in the array.
Monoidal fold over the inner most dimension.
Reduce each inner slice into a monoid and mappend results together
import Data.Massiv.Array as Aimport Data.Monoid (Product(..))arr = computeAs P $ iterateN (Sz2 2 3) (+1) (10 :: Int)arrArray P Seq (Sz (2 :. 3)) [ [ 11, 12, 13 ] , [ 14, 15, 16 ] ]getProduct $ foldInnerSlice (\column -> Product (A.sum column)) arr19575(11 + 14) * (12 + 15) * (13 + 16) :: Int19575
Reduce each outer slice into a monoid and mappend results together
import Data.Massiv.Array as Aimport Data.Monoid (Product(..))arr = computeAs P $ iterateN (Sz2 2 3) (+1) (10 :: Int)arrArray P Seq (Sz (2 :. 3)) [ [ 11, 12, 13 ] , [ 14, 15, 16 ] ]getProduct $ foldOuterSlice (\row -> Product (A.sum row)) arr1620(11 + 12 + 13) * (14 + 15 + 16) :: Int1620
foldSemi O(n) - Semigroup fold over an array.
Monoidal fold over some internal dimension.
Monoidal fold over some internal dimension. This is a pratial function and will result in IndexDimensionException if supplied dimension is invalid.
Left fold over the inner most dimension.
Left fold along a specified dimension.
import Data.Massiv.Array:set -XTypeApplicationsarr = makeArrayLinear @U Seq (Sz (2 :. 5)) idarrArray U Seq (Sz (2 :. 5)) [ [ 0, 1, 2, 3, 4 ] , [ 5, 6, 7, 8, 9 ] ]foldlWithin Dim1 (flip (:)) [] arrArray D Seq (Sz1 2) [ [4,3,2,1,0], [9,8,7,6,5] ]foldlWithin Dim2 (flip (:)) [] arrArray D Seq (Sz1 5) [ [5,0], [6,1], [7,2], [8,3], [9,4] ]
Similar to foldlWithin, except that dimension is specified at a value level, which means it will throw an exception on an invalid dimension.
Right fold over the inner most dimension.
Right fold along a specified dimension.
Similar to foldrWithin, except that dimension is specified at a value level, which means it will throw an exception on an invalid dimension.
Reduce each inner slice into a monoid with an index aware function and mappend results together
ifoldMono O(n) - Monoidal fold over an array with an index aware function. Also known as reduce.
Reduce each outer slice into a monoid with an index aware function and mappend results together
ifoldSemi O(n) - Semigroup fold over an array with an index aware function.
Left fold over the inner most dimension with index aware function.
Left fold along a specified dimension with an index aware function.
Similar to ifoldlWithin, except that dimension is specified at a value level, which means it will throw an exception on an invalid dimension.
Right fold over the inner most dimension with index aware function.
Right fold along a specified dimension with an index aware function.
Similar to ifoldrWithin, except that dimension is specified at a value level, which means it will throw an exception on an invalid dimension.
O(n) - Compute maximum of all elements.
O(n) - Compute maximum of all elements.
O(n) - Compute minimum of all elements.
O(n) - Compute minimum of all elements.
O(n) - Compute disjunction of all elements.
O(n) - Compute product of all elements.
O(n) - Compute sum of all elements.
O(n) - Determines whether any element of the array satisfies a predicate.
O(n) - Unstructured fold of an array.
foldMono O(n) - Monadic left fold.
O(n) - Monadic left fold, that discards the result.
foldlP O(n) - Left fold, computed with respect of array's computation strategy. Because we do potentially split the folding among many threads, we also need a combining function and an accumulator for the results. Depending on the number of threads being used, results can be different, hence is the MonadIO constraint.
import Data.Massiv.ArrayfoldlP (flip (:)) [] (flip (:)) [] $ makeArrayR D Seq (Sz1 6) id[[5,4,3,2,1,0]]foldlP (flip (:)) [] (++) [] $ makeArrayR D Seq (Sz1 6) id[5,4,3,2,1,0]foldlP (flip (:)) [] (flip (:)) [] $ makeArrayR D (ParN 3) (Sz1 6) id[[5,4],[3,2],[1,0]]foldlP (flip (:)) [] (++) [] $ makeArrayR D (ParN 3) (Sz1 6) id[1,0,3,2,5,4]
O(n) - Left fold, computed sequentially.
Version of foldr that supports foldr/build list fusion implemented by GHC.
O(n) - Monadic right fold.
O(n) - Monadic right fold, that discards the result.
O(n) - Right fold, computed with respect to computation strategy. Same as foldlP, except directed from the last element in the array towards beginning.
import Data.Massiv.ArrayfoldrP (:) [] (++) [] $ makeArrayR D (ParN 2) (Sz2 2 3) fromIx2[(0,0),(0,1),(0,2),(1,0),(1,1),(1,2)]foldrP (:) [] (:) [] $ makeArrayR D Seq (Sz1 6) id[[0,1,2,3,4,5]]foldrP (:) [] (:) [] $ makeArrayR D (ParN 3) (Sz1 6) id[[0,1],[2,3],[4,5]]
O(n) - Right fold, computed sequentially.
ifoldlIO :: (MonadUnliftIO m, Index ix, Source r e)=> (a -> ix -> e -> m a)Index aware folding IO action
-> aAccumulator
-> (b -> a -> m b)Folding action that is applied to the results of a parallel fold
-> bAccumulator for chunks folding
-> Array r ix e-> m bSimilar to ifoldlP, except that folding functions themselves do live in IO
O(n) - Monadic left fold with an index aware function.
O(n) - Monadic left fold with an index aware function, that discards the result.
O(n) - Left fold with an index aware function, computed in parallel. Just like foldlP, except that folding function will receive an index of an element it is being applied to.
O(n) - Left fold with an index aware function, computed sequentially.
Similar to ifoldrP, except that folding functions themselves do live in IO
O(n) - Monadic right fold with an index aware function.
O(n) - Monadic right fold with an index aware function, that discards the result.
O(n) - Right fold with an index aware function, while respecting the computation strategy. Same as ifoldlP, except directed from the last element in the array towards beginning, but also row-major.
O(n) - Right fold with an index aware function, computed sequentially.
O(n) - Left fold, computed sequentially with lazy accumulator.
O(n) - Right fold, computed sequentially with lazy accumulator.
Append two arrays together along the outer most dimension. Inner dimensions must agree, otherwise SizeMismatchException.
Concat arrays together along the outer most dimension. Inner dimensions must agree for all arrays in the list, otherwise SizeMismatchException.
Same as appendM, but will throw an exception in pure code on mismatched sizes.
Append two arrays together along a particular dimension. Sizes of both arrays must match, with an allowed exception of the dimension they are being appended along, otherwise Nothing is returned.
Append two 2D arrays along both dimensions. Note that they do agree on inner dimensions.
import Data.Massiv.ArrayarrA = makeArrayR U Seq (Sz2 2 3) (\(i :. j) -> ('A', i, j))arrB = makeArrayR U Seq (Sz2 2 3) (\(i :. j) -> ('B', i, j))appendM 1 arrA arrBArray DL Seq (Sz (2 :. 6)) [ [ ('A',0,0), ('A',0,1), ('A',0,2), ('B',0,0), ('B',0,1), ('B',0,2) ] , [ ('A',1,0), ('A',1,1), ('A',1,2), ('B',1,0), ('B',1,1), ('B',1,2) ] ]appendM 2 arrA arrBArray DL Seq (Sz (4 :. 3)) [ [ ('A',0,0), ('A',0,1), ('A',0,2) ] , [ ('A',1,0), ('A',1,1), ('A',1,2) ] , [ ('B',0,0), ('B',0,1), ('B',0,2) ] , [ ('B',1,0), ('B',1,1), ('B',1,2) ] ]
Now appending arrays with different sizes:
arrC = makeArrayR U Seq (Sz (2 :. 4)) (\(i :. j) -> ('C', i, j))appendM 1 arrA arrCArray DL Seq (Sz (2 :. 7)) [ [ ('A',0,0), ('A',0,1), ('A',0,2), ('C',0,0), ('C',0,1), ('C',0,2), ('C',0,3) ] , [ ('A',1,0), ('A',1,1), ('A',1,2), ('C',1,0), ('C',1,1), ('C',1,2), ('C',1,3) ] ]appendM 2 arrA arrC*** Exception: SizeMismatchException: (Sz (2 :. 3)) vs (Sz (2 :. 4))
backpermute' Similar to backpermuteM, with a few notable differences:
Creates a delayed array, instead of manifest, therefore it can be fused
Respects computation strategy, so it can be parallelized
Throws a runtime IndexOutOfBoundsException from pure code.
backpermuteM :: (Manifest r e, Index ix, Source r' e, Index ix', MonadUnliftIO m, PrimMonad m, MonadThrow m)=> Sz ixSize of the result array
-> (ix -> ix')A function that maps indices of the new array into the source one.
-> Array r' ix' eSource array.
-> m (Array r ix e)Rearrange elements of an array into a new one by using a function that maps indices of the newly created one into the old one. This function can throw IndexOutOfBoundsException.
import Data.Massiv.Array:set -XTypeApplicationsarr = makeArrayLinear @D Seq (Sz (2 :> 3 :. 4)) idarrArray D Seq (Sz (2 :> 3 :. 4)) [ [ [ 0, 1, 2, 3 ] , [ 4, 5, 6, 7 ] , [ 8, 9, 10, 11 ] ] , [ [ 12, 13, 14, 15 ] , [ 16, 17, 18, 19 ] , [ 20, 21, 22, 23 ] ] ]backpermuteM @U (Sz (4 :. 2)) (\(i :. j) -> j :> j :. i) arrArray U Seq (Sz (4 :. 2)) [ [ 0, 16 ] , [ 1, 17 ] , [ 2, 18 ] , [ 3, 19 ] ]
Concat many arrays together along some dimension.
Concatenate many arrays together along some dimension. It is important that all sizes are equal, with an exception of the dimensions along which concatenation happens.
Exceptions: IndexDimensionException, SizeMismatchException
Similar to deleteRegionM, but drop a specified number of columns an array.
import Data.Massiv.Arrayarr = fromIx2 <$> (0 :. 0 ..: 3 :. 6)arrArray D Seq (Sz (3 :. 6)) [ [ (0,0), (0,1), (0,2), (0,3), (0,4), (0,5) ] , [ (1,0), (1,1), (1,2), (1,3), (1,4), (1,5) ] , [ (2,0), (2,1), (2,2), (2,3), (2,4), (2,5) ] ]deleteColumnsM 2 3 arrArray DL Seq (Sz (3 :. 3)) [ [ (0,0), (0,1), (0,5) ] , [ (1,0), (1,1), (1,5) ] , [ (2,0), (2,1), (2,5) ] ]
deleteRegionM Delete a region from an array along the specified dimension.
import Data.Massiv.Arrayarr = fromIx3 <$> (0 :> 0 :. 0 ..: 3 :> 2 :. 6)deleteRegionM 1 2 3 arrArray DL Seq (Sz (3 :> 2 :. 3)) [ [ [ (0,0,0), (0,0,1), (0,0,5) ] , [ (0,1,0), (0,1,1), (0,1,5) ] ] , [ [ (1,0,0), (1,0,1), (1,0,5) ] , [ (1,1,0), (1,1,1), (1,1,5) ] ] , [ [ (2,0,0), (2,0,1), (2,0,5) ] , [ (2,1,0), (2,1,1), (2,1,5) ] ] ]v = Ix1 0 ... 10deleteRegionM 1 3 5 vArray DL Seq (Sz1 6) [ 0, 1, 2, 8, 9, 10 ]
Similar to deleteRegionM, but drop a specified number of rows from an array that has at least 2 dimensions.
import Data.Massiv.Arrayarr = fromIx2 <$> (0 :. 0 ..: 3 :. 6)arrArray D Seq (Sz (3 :. 6)) [ [ (0,0), (0,1), (0,2), (0,3), (0,4), (0,5) ] , [ (1,0), (1,1), (1,2), (1,3), (1,4), (1,5) ] , [ (2,0), (2,1), (2,2), (2,3), (2,4), (2,5) ] ]deleteRowsM 1 1 arrArray DL Seq (Sz (2 :. 6)) [ [ (0,0), (0,1), (0,2), (0,3), (0,4), (0,5) ] , [ (2,0), (2,1), (2,2), (2,3), (2,4), (2,5) ] ]
Discard elements from the source array according to the stride.
extract' Same as extractM, but will throw a runtime exception from pure code if supplied dimensions are incorrect.
extractFromTo' Same as extractFromToM, but throws an error on invalid indices.
extractFromToM Similar to extractM, except it takes starting and ending index. Result array will not include the ending index.
a <- resizeM (Sz (3 :> 2 :. 4)) $ Ix1 11 ... 34aArray D Seq (Sz (3 :> 2 :. 4)) [ [ [ 11, 12, 13, 14 ] , [ 15, 16, 17, 18 ] ] , [ [ 19, 20, 21, 22 ] , [ 23, 24, 25, 26 ] ] , [ [ 27, 28, 29, 30 ] , [ 31, 32, 33, 34 ] ] ]extractFromToM (1 :> 0 :. 1) (3 :> 2 :. 4) aArray D Seq (Sz (2 :> 2 :. 3)) [ [ [ 20, 21, 22 ] , [ 24, 25, 26 ] ] , [ [ 28, 29, 30 ] , [ 32, 33, 34 ] ] ]
extractM Extract a sub-array from within a larger source array. Array that is being extracted must be fully encapsulated in a source array, otherwise SizeSubregionException will be thrown.
import Data.Massiv.Array as Am <- resizeM (Sz (3 :. 3)) $ Ix1 1 ... 9mArray D Seq (Sz (3 :. 3)) [ [ 1, 2, 3 ] , [ 4, 5, 6 ] , [ 7, 8, 9 ] ]extractM (0 :. 1) (Sz (2 :. 2)) mArray D Seq (Sz (2 :. 2)) [ [ 2, 3 ] , [ 5, 6 ] ]a <- resizeM (Sz (3 :> 2 :. 4)) $ Ix1 11 ... 34aArray D Seq (Sz (3 :> 2 :. 4)) [ [ [ 11, 12, 13, 14 ] , [ 15, 16, 17, 18 ] ] , [ [ 19, 20, 21, 22 ] , [ 23, 24, 25, 26 ] ] , [ [ 27, 28, 29, 30 ] , [ 31, 32, 33, 34 ] ] ]extractM (0 :> 1 :. 1) (Sz (3 :> 1 :. 2)) aArray D Seq (Sz (3 :> 1 :. 2)) [ [ [ 16, 17 ] ] , [ [ 24, 25 ] ] , [ [ 32, 33 ] ] ]
O(1) - Reduce a multi-dimensional array into a flat vector
Replace an outer slice of an array with another one
import Data.Massiv.Arrayarr = makeArrayR U Seq (Sz3 3 4 5) fromIx3arr' = makeArrayR U Seq (Sz3 3 4 5) (fromIx3 . liftIndex (* 100))replaceOuterSlice 1 (arr' !> 2) arrArray DL Seq (Sz (3 :> 4 :. 5)) [ [ [ (0,0,0), (0,0,1), (0,0,2), (0,0,3), (0,0,4) ] , [ (0,1,0), (0,1,1), (0,1,2), (0,1,3), (0,1,4) ] , [ (0,2,0), (0,2,1), (0,2,2), (0,2,3), (0,2,4) ] , [ (0,3,0), (0,3,1), (0,3,2), (0,3,3), (0,3,4) ] ] , [ [ (200,0,0), (200,0,100), (200,0,200), (200,0,300), (200,0,400) ] , [ (200,100,0), (200,100,100), (200,100,200), (200,100,300), (200,100,400) ] , [ (200,200,0), (200,200,100), (200,200,200), (200,200,300), (200,200,400) ] , [ (200,300,0), (200,300,100), (200,300,200), (200,300,300), (200,300,400) ] ] , [ [ (2,0,0), (2,0,1), (2,0,2), (2,0,3), (2,0,4) ] , [ (2,1,0), (2,1,1), (2,1,2), (2,1,3), (2,1,4) ] , [ (2,2,0), (2,2,1), (2,2,2), (2,2,3), (2,2,4) ] , [ (2,3,0), (2,3,1), (2,3,2), (2,3,3), (2,3,4) ] ] ]
Replace a slice of an array with another one
import Data.Massiv.Arrayarr = makeArrayR U Seq (Sz3 3 4 5) fromIx3arr' = makeArrayR U Seq (Sz3 3 4 5) (fromIx3 . liftIndex (* 100))replaceSlice 2 1 (arr' <!> (2, 3)) arrArray DL Seq (Sz (3 :> 4 :. 5)) [ [ [ (0,0,0), (0,0,1), (0,0,2), (0,0,3), (0,0,4) ] , [ (0,300,0), (0,300,100), (0,300,200), (0,300,300), (0,300,400) ] , [ (0,2,0), (0,2,1), (0,2,2), (0,2,3), (0,2,4) ] , [ (0,3,0), (0,3,1), (0,3,2), (0,3,3), (0,3,4) ] ] , [ [ (1,0,0), (1,0,1), (1,0,2), (1,0,3), (1,0,4) ] , [ (100,300,0), (100,300,100), (100,300,200), (100,300,300), (100,300,400) ] , [ (1,2,0), (1,2,1), (1,2,2), (1,2,3), (1,2,4) ] , [ (1,3,0), (1,3,1), (1,3,2), (1,3,3), (1,3,4) ] ] , [ [ (2,0,0), (2,0,1), (2,0,2), (2,0,3), (2,0,4) ] , [ (200,300,0), (200,300,100), (200,300,200), (200,300,300), (200,300,400) ] , [ (2,2,0), (2,2,1), (2,2,2), (2,2,3), (2,2,4) ] , [ (2,3,0), (2,3,1), (2,3,2), (2,3,3), (2,3,4) ] ] ]
Same as resizeM, but will throw an error if supplied dimensions are incorrect.
O(1) - Change the size of an array. Throws SizeElementsMismatchException if total number of elements does not match the supplied array.
Reverse an array along some dimension. Dimension supplied is checked at compile time.
import Data.Massiv.Array as Aarr = makeArrayLinear Seq (Sz2 4 5) (+10) :: Array D Ix2 IntarrArray D Seq (Sz (4 :. 5)) [ [ 10, 11, 12, 13, 14 ] , [ 15, 16, 17, 18, 19 ] , [ 20, 21, 22, 23, 24 ] , [ 25, 26, 27, 28, 29 ] ]A.reverse Dim1 arrArray D Seq (Sz (4 :. 5)) [ [ 14, 13, 12, 11, 10 ] , [ 19, 18, 17, 16, 15 ] , [ 24, 23, 22, 21, 20 ] , [ 29, 28, 27, 26, 25 ] ]A.reverse Dim2 arrArray D Seq (Sz (4 :. 5)) [ [ 25, 26, 27, 28, 29 ] , [ 20, 21, 22, 23, 24 ] , [ 15, 16, 17, 18, 19 ] , [ 10, 11, 12, 13, 14 ] ]
Reverse an array along some dimension. Same as reverseM, but throws the IndexDimensionException from pure code.
Similarly to reverse, flip an array along a particular dimension, but throws IndexDimensionException for an incorrect dimension.
O(1) - Split an array into two at an index along a specified dimension. Throws an error for a wrong dimension or incorrect indices.
Related: splitAtM, splitExtractM, sliceAt', sliceAtM
splitAtM O(1) - Split an array into two at an index along a specified dimension.
Related: splitAt', splitExtractM, sliceAt', sliceAtM
Exceptions: IndexDimensionException, SizeSubregionException
splitExtractM Split an array in three parts across some dimension
Specialized stackSlicesM to handling stacking from the inside. It is the inverse of innerSlices.
Exceptions: SizeMismatchException
In this example we stack vectors as columns of a matrix from left to right:
import Data.Massiv.Array as Ax = compute (iterateN 3 succ 0) :: Matrix P IntxArray P Seq (Sz (3 :. 3)) [ [ 1, 2, 3 ] , [ 4, 5, 6 ] , [ 7, 8, 9 ] ]columns = innerSlices xA.mapM_ print columnsArray D Seq (Sz1 3) [ 1, 4, 7 ]Array D Seq (Sz1 3) [ 2, 5, 8 ]Array D 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 ] ]
Specialized stackSlicesM to handling stacking from the outside. It is the inverse of outerSlices.
Exceptions: SizeMismatchException
In this example we stack vectors as row of a matrix from top to bottom:
import Data.Massiv.Array as Ax = compute (iterateN 3 succ 0) :: Matrix P IntxArray P Seq (Sz (3 :. 3)) [ [ 1, 2, 3 ] , [ 4, 5, 6 ] , [ 7, 8, 9 ] ]rows = outerSlices xA.mapM_ print rowsArray P Seq (Sz1 3) [ 1, 2, 3 ]Array P Seq (Sz1 3) [ 4, 5, 6 ]Array P 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 ] ]
Stack slices on top of each other along the specified dimension.
Exceptions: IndexDimensionException, SizeMismatchException
Here are the three different ways to stack up two 2D Matrix pages into a 3D array.
import Data.Massiv.Array as Ax = compute (iterateN 3 succ 0) :: Matrix P Inty = compute (iterateN 3 succ 9) :: Matrix P IntxArray P Seq (Sz (3 :. 3)) [ [ 1, 2, 3 ] , [ 4, 5, 6 ] , [ 7, 8, 9 ] ]yArray 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 ] ] ]
General array transformation
Same as transform', but operates on two arrays
Same as transformM, but operates on two arrays
General array transformation, that forces computation and produces a manifest array.
Transpose a 2-dimensional array
import Data.Massiv.Arrayarr = makeArrayLinearR D Seq (Sz (2 :. 3)) idarrArray D Seq (Sz (2 :. 3)) [ [ 0, 1, 2 ] , [ 3, 4, 5 ] ]transpose arrArray D Seq (Sz (3 :. 2)) [ [ 0, 3 ] , [ 1, 4 ] , [ 2, 5 ] ]
Transpose inner two dimensions of at least rank-2 array.
import Data.Massiv.Arrayarr = makeArrayLinearR U Seq (Sz (2 :> 3 :. 4)) idarrArray U Seq (Sz (2 :> 3 :. 4)) [ [ [ 0, 1, 2, 3 ] , [ 4, 5, 6, 7 ] , [ 8, 9, 10, 11 ] ] , [ [ 12, 13, 14, 15 ] , [ 16, 17, 18, 19 ] , [ 20, 21, 22, 23 ] ] ]transposeInner arrArray D Seq (Sz (3 :> 2 :. 4)) [ [ [ 0, 1, 2, 3 ] , [ 12, 13, 14, 15 ] ] , [ [ 4, 5, 6, 7 ] , [ 16, 17, 18, 19 ] ] , [ [ 8, 9, 10, 11 ] , [ 20, 21, 22, 23 ] ] ]
Transpose outer two dimensions of at least rank-2 array.
import Data.Massiv.Array:set -XTypeApplicationsarr = makeArrayLinear @U Seq (Sz (2 :> 3 :. 4)) idarrArray U Seq (Sz (2 :> 3 :. 4)) [ [ [ 0, 1, 2, 3 ] , [ 4, 5, 6, 7 ] , [ 8, 9, 10, 11 ] ] , [ [ 12, 13, 14, 15 ] , [ 16, 17, 18, 19 ] , [ 20, 21, 22, 23 ] ] ]transposeOuter arrArray D Seq (Sz (2 :> 4 :. 3)) [ [ [ 0, 4, 8 ] , [ 1, 5, 9 ] , [ 2, 6, 10 ] , [ 3, 7, 11 ] ] , [ [ 12, 16, 20 ] , [ 13, 17, 21 ] , [ 14, 18, 22 ] , [ 15, 19, 23 ] ] ]
upsample Insert the same element into a Loadable array according to the supplied stride.
import Data.Massiv.Array as Aarr = iterateN (Sz2 3 2) succ (0 :: Int)arrArray DL Seq (Sz (3 :. 2)) [ [ 1, 2 ] , [ 3, 4 ] , [ 5, 6 ] ]upsample 0 (Stride (2 :. 3)) arrArray 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)) arrArray DL Seq (Sz (3 :. 4)) [ [ 1, 9, 2, 9 ] , [ 3, 9, 4, 9 ] , [ 5, 9, 6, 9 ] ]
zoom Increaze the size of the array accoridng to the stride multiplier while replicating the same element to fill the neighbors. It is exactly the same as zoomWithGrid, but without the grid.
import Data.Massiv.Array as Aarr = resize' (Sz3 1 3 2) (Ix1 1 ... 6)arrArray D Seq (Sz (1 :> 3 :. 2)) [ [ [ 1, 2 ] , [ 3, 4 ] , [ 5, 6 ] ] ]zoom (Stride (2 :> 2 :. 3)) arrArray DL Seq (Sz (2 :> 6 :. 6)) [ [ [ 1, 1, 1, 2, 2, 2 ] , [ 1, 1, 1, 2, 2, 2 ] , [ 3, 3, 3, 4, 4, 4 ] , [ 3, 3, 3, 4, 4, 4 ] , [ 5, 5, 5, 6, 6, 6 ] , [ 5, 5, 5, 6, 6, 6 ] ] , [ [ 1, 1, 1, 2, 2, 2 ] , [ 1, 1, 1, 2, 2, 2 ] , [ 3, 3, 3, 4, 4, 4 ] , [ 3, 3, 3, 4, 4, 4 ] , [ 5, 5, 5, 6, 6, 6 ] , [ 5, 5, 5, 6, 6, 6 ] ] ]
zoomWithGrid Replicate each element of the array by a factor in stride along each dimension and surround each such group with a box of supplied grid value. It will essentially zoom up an array and create a grid around each element from the original array. Very useful for zooming up images to inspect individual pixels.
import Data.Massiv.Array as Aarr = resize' (Sz2 3 2) (Ix1 1 ... 6)arrArray D Seq (Sz (3 :. 2)) [ [ 1, 2 ] , [ 3, 4 ] , [ 5, 6 ] ]zoomWithGrid 0 (Stride (2 :. 3)) arrArray DL Seq (Sz (10 :. 9)) [ [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ] , [ 0, 1, 1, 1, 0, 2, 2, 2, 0 ] , [ 0, 1, 1, 1, 0, 2, 2, 2, 0 ] , [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ] , [ 0, 3, 3, 3, 0, 4, 4, 4, 0 ] , [ 0, 3, 3, 3, 0, 4, 4, 4, 0 ] , [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ] , [ 0, 5, 5, 5, 0, 6, 6, 6, 0 ] , [ 0, 5, 5, 5, 0, 6, 6, 6, 0 ] , [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ] ]
O(1) - Slices the array from the outside. For 2-dimensional array this will be equivalent of taking a row. Throws an error when index is out of bounds.
You could say that slicing from outside is synonymous to slicing from the end or slicing at the highermost dimension. For example with rank-3 arrays outer slice would be equivalent to getting a page:
import Data.Massiv.Arrayarr = makeArrayR U Seq (Sz (3 :> 2 :. 4)) fromIx3arrArray U Seq (Sz (3 :> 2 :. 4)) [ [ [ (0,0,0), (0,0,1), (0,0,2), (0,0,3) ] , [ (0,1,0), (0,1,1), (0,1,2), (0,1,3) ] ] , [ [ (1,0,0), (1,0,1), (1,0,2), (1,0,3) ] , [ (1,1,0), (1,1,1), (1,1,2), (1,1,3) ] ] , [ [ (2,0,0), (2,0,1), (2,0,2), (2,0,3) ] , [ (2,1,0), (2,1,1), (2,1,2), (2,1,3) ] ] ]arr !> 2Array U Seq (Sz (2 :. 4)) [ [ (2,0,0), (2,0,1), (2,0,2), (2,0,3) ] , [ (2,1,0), (2,1,1), (2,1,2), (2,1,3) ] ]
There is nothing wrong with chaining, mixing and matching slicing operators:
arr !> 2 !> 0 ! 3(2,0,3)evaluateM (arr !> 2 <! 3) 0(2,0,3)(arr !> 2 !> 0 ! 3) == (arr ! 2 :> 0 :. 3)True
O(1) - Similarly to (!>) slice an array from an opposite direction.
O(1) - Slices the array in any available dimension. Throws an error when index is out of bounds or dimensions is invalid.
O(1) - Safe slice from the inside
O(1) - Safe slicing continuation from the inside
O(1) - Safe slicing continuation from within.
O(1) - Safe slicing continuation from the outside. Similarly to (!>) slices the array from the outside, but takes Maybe array as input and returns Nothing when index is out of bounds.
import Data.Massiv.Arrayarr = makeArrayR U Seq (Sz (3 :> 2 :. 4)) fromIx3arr !?> 2 ??> 0 ?? 3 :: Maybe Ix3TJust (2,0,3)arr !?> 2 ??> 0 ?? -1 :: Maybe Ix3TNothingarr !?> 2 ??> -10 ?? 1*** Exception: IndexOutOfBoundsException: -10 is not safe for (Sz1 2)
Create a delayed array of inner slices.
import Data.Massiv.Array as AA.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 ]
Create a delayed array of outer slices.
import Data.Massiv.Array as AA.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 ]
Create a delayed array of slices from within. Checks dimension at compile time.
import Data.Massiv.Array as Aarr = fromIx3 <$> (0 ..: (4 :> 3 :. 2))print arrArray 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 arrArray 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) ] ]
Create a delayed array of slices from within. Same as withinSlices, but throws an error on invalid dimension.
Throws Exceptions: IndexDimensionException
This is an implementation of Quicksort, which is an efficient, but unstable sort. This implementation 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.
Same as quicksortBy, but instead of Ord constraint expects a custom Ordering.
Same as quicksortBy, but instead of Ord constraint expects a custom Ordering.
Count number of occurrences of each element in the array. Results will be sorted in ascending order of the element.
import Data.Massiv.Array as Axs = fromList Seq [2, 4, 3, 2, 4, 5, 2, 1] :: Array P Ix1 IntxsArray P Seq (Sz1 8) [ 2, 4, 3, 2, 4, 5, 2, 1 ]tally xsArray DS Seq (Sz1 5) [ (1,1), (2,3), (3,1), (4,2), (5,1) ]
iterateUntil :: (Load r' ix e, Manifest r e, NFData (Array r ix e))=> (Int -> Array r ix e -> Array r ix e -> Bool)Convergence condition. Accepts current iteration counter, array at the previous state and at the current state.
-> (Int -> Array r ix e -> Array r' ix e)A modifying function to apply at each iteration. The size of resulting array may differ if necessary
-> Array r ix eInitial source array
-> Array r ix eEfficiently iterate a function until a convergence condition is satisfied. If the size of array doesn't change between iterations then no more than two new arrays will be allocated, regardless of the number of iterations. If the size does change from one iteration to another, an attempt will be made to grow/shrink the intermediate mutable array instead of allocating a new one.
import Data.Massiv.Arraylet arr = computeAs P $ makeLoadArrayS (Sz2 8 8) (0 :: Int) $ \ w -> () <$ w (0 :. 0) 1arrArray P Seq (Sz (8 :. 8)) [ [ 1, 0, 0, 0, 0, 0, 0, 0 ] , [ 0, 0, 0, 0, 0, 0, 0, 0 ] , [ 0, 0, 0, 0, 0, 0, 0, 0 ] , [ 0, 0, 0, 0, 0, 0, 0, 0 ] , [ 0, 0, 0, 0, 0, 0, 0, 0 ] , [ 0, 0, 0, 0, 0, 0, 0, 0 ] , [ 0, 0, 0, 0, 0, 0, 0, 0 ] , [ 0, 0, 0, 0, 0, 0, 0, 0 ] ]let nextPascalRow cur above = if cur == 0 then above else curlet pascal = makeStencil (Sz2 2 2) 1 $ \ get -> nextPascalRow (get (0 :. 0)) (get (-1 :. -1) + get (-1 :. 0))iterateUntil (\_ _ a -> (a ! (7 :. 7)) /= 0) (\ _ -> mapStencil (Fill 0) pascal) arrArray P Seq (Sz (8 :. 8)) [ [ 1, 0, 0, 0, 0, 0, 0, 0 ] , [ 1, 1, 0, 0, 0, 0, 0, 0 ] , [ 1, 2, 1, 0, 0, 0, 0, 0 ] , [ 1, 3, 3, 1, 0, 0, 0, 0 ] , [ 1, 4, 6, 4, 1, 0, 0, 0 ] , [ 1, 5, 10, 10, 5, 1, 0, 0 ] , [ 1, 6, 15, 20, 15, 6, 1, 0 ] , [ 1, 7, 21, 35, 35, 21, 7, 1 ] ]
Convert a flat list into a vector
fromLists' Same as fromListsM, but will throw an error on irregular shaped lists.
Note: This function is the same as if you would turn on {-# LANGUAGE OverloadedLists #-}
extension. For that reason you can also use GHC.Exts.fromList.
\xs -> fromLists' Seq xs == (fromList Seq xs :: Vector P Int)Convert a list of lists into a 2D Array
import Data.Massiv.Array as AfromLists' Seq [[1,2,3],[4,5,6]] :: Array U Ix2 IntArray U Seq (Sz (2 :. 3)) [ [ 1, 2, 3 ] , [ 4, 5, 6 ] ]
Above example implemented using GHC's OverloadedLists extension:
:set -XOverloadedLists[[1,2,3],[4,5,6]] :: Array U Ix2 IntArray U Seq (Sz (2 :. 3)) [ [ 1, 2, 3 ] , [ 4, 5, 6 ] ]
O(n) - Convert a nested list into an array. Nested list must be of a rectangular shape, otherwise a runtime error will occur. Also, nestedness must match the rank of resulting array, which should be specified through an explicit type signature.
import Data.Massiv.Array as AfromListsM Seq [[1,2,3],[4,5,6]] :: Maybe (Array U Ix2 Int)Just (Array U Seq (Sz (2 :. 3)) [ [ 1, 2, 3 ] , [ 4, 5, 6 ] ])
fromListsM Par [[[1,2,3]],[[4,5,6]]] :: Maybe (Array U Ix3 Int)Just (Array U Par (Sz (2 :> 1 :. 3)) [ [ [ 1, 2, 3 ] ] , [ [ 4, 5, 6 ] ] ])
Elements of a boxed array could be lists themselves if necessary, but cannot be ragged:
fromListsM Seq [[[1,2,3]],[[4,5]]] :: Maybe (Array B Ix2 [Int])Just (Array B Seq (Sz (2 :. 1)) [ [ [1,2,3] ] , [ [4,5] ] ])fromListsM Seq [[[1,2,3]],[[4,5]]] :: Maybe (Array B Ix3 Integer)NothingfromListsM Seq [[[1,2,3]],[[4,5,6],[7,8,9]]] :: IO (Array B Ix3 Integer)*** Exception: DimTooLongException for (Dim 2): expected (Sz1 1), got (Sz1 2)fromListsM Seq [[1,2,3,4],[5,6,7]] :: IO (Matrix B Integer)*** Exception: DimTooShortException for (Dim 1): expected (Sz1 4), got (Sz1 3)
Convert any array to a flat list.
import Data.Massiv.ArraytoList $ makeArrayR U Seq (Sz (2 :. 3)) fromIx2[(0,0),(0,1),(0,2),(1,0),(1,1),(1,2)]
toLists O(n) - Convert an array into a nested list. Number of array dimensions and list nestedness will always match, but you can use toList, toLists2, etc. if flattening of inner dimensions is desired.
Note: This function is almost the same as toList.
import Data.Massiv.Arrayarr = makeArrayR U Seq (Sz (2 :> 1 :. 3)) idarrArray U Seq (Sz (2 :> 1 :. 3)) [ [ [ 0 :> 0 :. 0, 0 :> 0 :. 1, 0 :> 0 :. 2 ] ] , [ [ 1 :> 0 :. 0, 1 :> 0 :. 1, 1 :> 0 :. 2 ] ] ]toLists arr[[[0 :> 0 :. 0,0 :> 0 :. 1,0 :> 0 :. 2]],[[1 :> 0 :. 0,1 :> 0 :. 1,1 :> 0 :. 2]]]
Convert an array with at least 2 dimensions into a list of lists. Inner dimensions will get flattened.
import Data.Massiv.ArraytoLists2 $ makeArrayR U Seq (Sz2 2 3) fromIx2[[(0,0),(0,1),(0,2)],[(1,0),(1,1),(1,2)]]toLists2 $ makeArrayR U Seq (Sz3 2 1 3) fromIx3[[(0,0,0),(0,0,1),(0,0,2)],[(1,0,0),(1,0,1),(1,0,2)]]
Convert an array with at least 3 dimensions into a 3 deep nested list. Inner dimensions will get flattened.
Convert an array with at least 4 dimensions into a 4 deep nested list. Inner dimensions will get flattened.
module Data.Massiv.Array.Mutable
module Data.Massiv.Core
module Data.Massiv.Array.Delayed
module Data.Massiv.Array.Manifest
module Data.Massiv.Array.Stencil
module Data.Massiv.Array.Numeric