massiv
Massiv (Массив) is an Array Library.
https://github.com/lehins/massiv
LTS Haskell 22.12:  1.0.4.0 
Stackage Nightly 20240301:  1.0.4.0 
Latest on Hackage:  1.0.4.0 
massiv1.0.4.0@sha256:6fce54a305f4d6da5a929d8720bf3324ea62d3464dc4b24721be605bcd794a0f,5246
Module documentation for 1.0.4.0
 Data
 Data.Massiv
 Data.Massiv.Array
 Data.Massiv.Core
 Data.Massiv.Vector
 Data.Massiv.Vector.Stream
 Data.Massiv
massiv
massiv
is a Haskell library for array manipulation. Performance is one of its main goals, thus it
is capable of seamless parallelization of most of the operations provided by the library
The name for this library comes from the Russian word Massiv (Масси́в), which means an Array.
Status
Language  Github Actions  Coveralls  Gitter.im 

Package  Hackage  Nightly  LTS 

massiv 

massivtest 

haskellscheduler 
Introduction
Everything in the library revolves around an Array r ix e
 a data family for anything that can be
thought of as an array. The type variables, from the end, are:
e
 element of an array.ix
 an index that will map to an actual element. The index must be an instance of theIndex
class with the default one being anIx n
type family and an optional being tuples ofInt
s.r
 underlying representation. There are two main categories of representations described below.
Manifest
These are your classical arrays that are located in memory and allow constant time lookup of
elements. Another main property they share is that they have a mutable interface. An Array
with
manifest representation can be thawed into a mutable MArray
and then frozen back into its
immutable counterpart after some destructive operation is applied to the mutable copy. The
differences among representations below is in the way that elements are being accessed in memory:
P
 Array with elements that are an instance ofPrim
type class, i.e. common Haskell primitive types:Int
,Word
,Char
, etc. It is backed by unpinned memory and based onByteArray
.U
 Unboxed arrays. The elements are instances of theUnbox
type class. Usually just as fast asP
, but has a slightly wider range of data types that it can work with. Notable data types that can be stored as elements areBool
, tuples andIx n
.S
 Storable arrays. Backed by pinned memory and based onForeignPtr
, while elements are instances of theStorable
type class.B
 Boxed arrays that don’t have restrictions on their elements, since they are represented as pointers to elements, thus making them the slowest type of array, but also the most general. Arrays of this representation are element strict, in other words its elements are kept in WeakHead Normal Form (WHNF).BN
 Also boxed arrays, but unlike the other representationB
, its elements are in Normal Form, i.e. in a fully evaluated state and no thunks or memory leaks are possible. It does require anNFData
instance for the elements though.BL
 Boxed lazy array. Just likeB
andBN
, except values are evaluated on demand.
Delayed
Main trait of delayed arrays is that they do not exist in memory and instead describe the contents
of an array as a function or a composition of functions. In fact all of the fusion capabilities in
massiv
can be attributed to delayed arrays.
D
 Delayed “pull” array is just a function from an index to an element:(ix > e)
. Therefore indexing into this type of array is not possible, instead elements are evaluated with theevaluateM
function each time when applied to an index. It gives us a nice ability to compose functions together when applied to an array and possibly even fold over without ever allocating intermediate manifest arrays.DW
 Delayed windowed array is very similar to the version above, except it has two functions that describe it, one for the near border elements and one for the interior, aka. the window. This is used forStencil
computation and things that derive from it, such as convolution, for instance.DL
 Delayed “push” array contains a monadic action that describes how an array can be loaded into memory. This is most useful for composing arrays together.DS
 Delayed stream array is a sequence of elements, possibly even an infinite one. This is most useful for situations when we don’t know the size of our resulting array ahead of time, which is common in operations such asfilter
,mapMaybe
,unfold
etc. Naturally, in the end we can only load such an array into a flat vector.DI
 Is just likeD
, except loading is interleaved and is useful for parallel loading arrays with unbalanced computation, such as Mandelbrot set or ray tracing, for example.
Construct
Creating a delayed type of array allows us to fuse any future operations we decide to perform on it. Let’s look at this example:
λ> import Data.Massiv.Array as A
λ> makeVectorR D Seq 10 id
Array D Seq (Sz1 10)
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
Here we created a delayed vector of size 10, which is in reality just an id
function from its
index to an element (see the Computation section for the meaning of Seq
). So let’s
go ahead and square its elements
λ> vec = makeVectorR D Seq 10 id
λ> evaluateM vec 4
4
λ> vec2 = A.map (^ (2 :: Int)) vec
λ> evaluateM vec2 4
16
It’s not that exciting, since every time we call evaluateM
it will recompute the element, every
time, therefore this function should be avoided at all costs! Instead we can use all of the
functions that take Source
like arrays and then fuse that computation together by calling
compute
, or a handy computeAs
function and only afterwards apply an indexM
function or its
partial synonym: (!)
. Any delayed array can also be reduced using one of the folding functions,
thus completely avoiding any memory allocation, or converted to a list, if that’s what you need:
λ> vec2U = computeAs U vec2
λ> vec2U
Array U Seq (Sz1 10)
[ 0, 1, 4, 9, 16, 25, 36, 49, 64, 81 ]
λ> vec2U ! 4
16
λ> toList vec2U
[0,1,4,9,16,25,36,49,64,81]
λ> A.sum vec2U
285
There is a whole multitude of ways to construct arrays:
 by using one of many helper functions:
makeArray
,range
,rangeStepFrom
,enumFromN
, etc.  through conversion: from lists, from
Vector
s invector
library, fromByteString
s inbytestring
;  with a mutable interface in
PrimMonad
(IO
,ST
, etc.), eg:makeMArray
,generateArray
,unfoldrPrim
, etc.
It’s worth noting that, in the next example, nested lists will be loaded into an unboxed manifest array and the sum of its elements will be computed in parallel on all available cores.
λ> A.sum (fromLists' Par [[0,0,0,0,0],[0,1,2,3,4],[0,2,4,6,8]] :: Array U Ix2 Double)
30.0
The above wouldn’t run in parallel in ghci of course, as the program would have to be compiled with
ghc
using threaded withrtsopts=N
flags in order to use all available cores. Alternatively we
could compile with the threaded
flag and then pass the number of capabilities directly to the
runtime with +RTS N<n>
, where <n>
is the number of cores you’d like to utilize.
Index
The main Ix n
closed type family can be somewhat confusing, but there is no need to fully
understand how it works in order to start using it. GHC might ask you for the DataKinds
language
extension if IxN n
is used in a type signature, but there are type and pattern synonyms for the
first five dimensions: Ix1
, Ix2
, Ix3
, Ix4
and Ix5
.
There are three distinguishable constructors for the index:
 The first one is simply an int:
Ix1 = Ix 1 = Int
, therefore vectors can be indexed in a usual way without some extra wrapping data type, just as it was demonstrated in a previous section.  The second one is
Ix2
for operating on 2dimensional arrays and has a constructor:.
λ> makeArrayR D Seq (Sz (3 :. 5)) (\ (i :. j) > i * j)
Array D Seq (Sz (3 :. 5))
[ [ 0, 0, 0, 0, 0 ]
, [ 0, 1, 2, 3, 4 ]
, [ 0, 2, 4, 6, 8 ]
]
 The third one is
IxN n
and is designed for working with Ndimensional arrays, and has a similar looking constructor:>
, except that it can be chained indefinitely on top of:.
λ> arr3 = makeArrayR P Seq (Sz (3 :> 2 :. 5)) (\ (i :> j :. k) > i * j + k)
λ> :t arr3
arr3 :: Array P (IxN 3) Int
λ> arr3
Array P Seq (Sz (3 :> 2 :. 5))
[ [ [ 0, 1, 2, 3, 4 ]
, [ 0, 1, 2, 3, 4 ]
]
, [ [ 0, 1, 2, 3, 4 ]
, [ 1, 2, 3, 4, 5 ]
]
, [ [ 0, 1, 2, 3, 4 ]
, [ 2, 3, 4, 5, 6 ]
]
]
λ> arr3 ! (2 :> 1 :. 4)
6
λ> ix10 = 10 :> 9 :> 8 :> 7 :> 6 :> 5 :> 4 :> 3 :> 2 :. 1
λ> :t ix10
ix10 :: IxN 10
λ> ix10  10dimensional index
10 :> 9 :> 8 :> 7 :> 6 :> 5 :> 4 :> 3 :> 2 :. 1
Here is how we can construct a 4dimensional array and sum its elements in constant memory:
λ> arr = makeArrayR D Seq (Sz (10 :> 20 :> 30 :. 40)) $ \ (i :> j :> k :. l) > (i * j + k) * k + l
λ> :t arr  a 4dimensional array
arr :: Array D (IxN 4) Int
λ> A.sum arr
221890000
There are quite a few helper functions that can operate on indices, but these are only needed when writing functions that work for arrays of arbitrary dimension, as such they are scarcely used:
λ> pullOutDim' ix10 5
(5,10 :> 9 :> 8 :> 7 :> 6 :> 4 :> 3 :> 2 :. 1)
λ> unconsDim ix10
(10,9 :> 8 :> 7 :> 6 :> 5 :> 4 :> 3 :> 2 :. 1)
λ> unsnocDim ix10
(10 :> 9 :> 8 :> 7 :> 6 :> 5 :> 4 :> 3 :. 2,1)
All of the Ix n
indices are instances of Num
so basic numeric operations are made easier:
λ> (1 :> 2 :. 3) + (4 :> 5 :. 6)
5 :> 7 :. 9
λ> 5 :: Ix4
5 :> 5 :> 5 :. 5
It is important to note that the size type is distinct from the index by the newtype wrapper Sz ix
. There is a constructor Sz
, which will make sure that none of the dimensions are negative:
λ> Sz (2 :> 3 :. 4)
Sz (2 :> 3 :. 4)
λ> Sz (10 :> 2 :> 30 :. 4)
Sz (10 :> 2 :> 0 :. 4)
Same as with indices, there are helper pattern synonyms: Sz1
, Sz2
, Sz3
, Sz4
and Sz5
.
λ> Sz3 2 3 4
Sz (2 :> 3 :. 4)
λ> Sz4 10 2 (30) 4
Sz (10 :> 2 :> 0 :. 4)
As well as the Num
instance:
λ> 4 :: Sz5
Sz (4 :> 4 :> 4 :> 4 :. 4)
λ> (Sz2 1 2) + 3
Sz (4 :. 5)
λ> (Sz2 1 2)  3
Sz (0 :. 0)
Alternatively tuples of Int
s can be used for working with arrays, up to and including 5tuples
(type synonyms: Ix2T
.. Ix5T
), but since tuples are polymorphic it is necessary to restrict the
resulting array type. Not all operations in the library support tuples, so it is advised to avoid
them for indexing.
λ> makeArray Seq (4, 20) (uncurry (*)) :: Array P Ix2T Int
(Array P Seq ((4,20))
[ [ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ]
, [ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 ]
, [ 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38 ]
, [ 0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 ]
])
λ> :i Ix2T
type Ix2T = (Int, Int)
There are helper functions that can go back and forth between tuples and Ix n
indices.
λ> fromIx4 (3 :> 4 :> 5 :. 6)
(3,4,5,6)
λ> toIx5 (3, 4, 5, 6, 7)
3 :> 4 :> 5 :> 6 :. 7
Slicing
In order to get a subsection of an array there is no need to recompute it, unless we want to free up the no longer memory, of course. So, there are a few slicing, resizing and extraction operators that can do it all in constant time, modulo the index manipulation:
λ> arr = makeArrayR U Seq (Sz (4 :> 2 :. 6)) fromIx3
λ> arr !> 3 !> 1
Array M Seq (Sz1 6)
[ (3,1,0), (3,1,1), (3,1,2), (3,1,3), (3,1,4), (3,1,5) ]
As you might suspect all of the slicing, indexing, extracting, resizing operations are partial, and
those are frowned upon in Haskell. So there are matching functions that can do the same operations
safely by using MonadThrow
and thus returning Nothing
, Left SomeException
or throwing an
exception in case of IO
on failure, for example:
λ> arr !?> 3 ??> 1
Array M Seq (Sz1 6)
[ (3,1,0), (3,1,1), (3,1,2), (3,1,3), (3,1,4), (3,1,5) ]
λ> arr !?> 3 ??> 1 ?? 0 :: Maybe (Int, Int, Int)
Just (3,1,0)
In above examples we first take a slice at the 4th page (index 3, since we start at 0), then another one at the 2nd row (index 1). While in the last example we also take 1st element at position 0. Pretty neat, huh? Naturally, by doing a slice we always reduce dimension by one. We can do slicing from the outside as well as from the inside:
λ> Ix1 1 ... 9
Array D Seq (Sz1 10)
[ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
λ> a < resizeM (Sz (3 :> 2 :. 4)) $ Ix1 11 ... 34
λ> a
Array 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 ]
]
]
λ> a !> 0
Array D Seq (Sz (2 :. 4))
[ [ 11, 12, 13, 14 ]
, [ 15, 16, 17, 18 ]
]
λ> a <! 0
Array D Seq (Sz (3 :. 2))
[ [ 11, 15 ]
, [ 19, 23 ]
, [ 27, 31 ]
]
Or we can slice along any other available dimension:
λ> a <!> (Dim 2, 0)
Array D Seq (Sz (3 :. 4))
[ [ 11, 12, 13, 14 ]
, [ 19, 20, 21, 22 ]
, [ 27, 28, 29, 30 ]
]
In order to extract subarray while preserving dimensionality we can use extractM
or extractFromToM
.
λ> extractM (0 :> 1 :. 1) (Sz (3 :> 1 :. 2)) a
Array D Seq (Sz (3 :> 1 :. 2))
[ [ [ 16, 17 ]
]
, [ [ 24, 25 ]
]
, [ [ 32, 33 ]
]
]
λ> extractFromToM (1 :> 0 :. 1) (3 :> 2 :. 4) a
Array D Seq (Sz (2 :> 2 :. 3))
[ [ [ 20, 21, 22 ]
, [ 24, 25, 26 ]
]
, [ [ 28, 29, 30 ]
, [ 32, 33, 34 ]
]
]
Computation and parallelism
There is a data type Comp
that controls how elements will be computed when calling the compute
function. It has a few constructors, although most of the time either Seq
or Par
will be
sufficient:
Seq
 computation will be done sequentially on one core (capability in ghc).ParOn [Int]
 perform computation in parallel while pinning the workers to particular cores. Providing an empty list will result in the computation being distributed over all available cores, or better known in Haskell as capabilities.ParN Word16
 similar toParOn
, except it simply specifies the number of cores to use, with0
meaning all cores.Par
 isn’t really a constructor but apattern
for constructingParOn []
, which will result in Scheduler using all cores, thus should be used instead ofParOn
.Par'
 similar toPar
, except it usesParN 0
underneath.
Just to make sure a simple novice mistake is prevented, which I have seen in the past, make sure
your source code is compiled with ghc O2 threaded withrtsopts=N
, otherwise no parallelization
and poor performance are waiting for you. Also a bit later you might notice the {# INLINE funcName #}
pragma being used, oftentimes it is a good idea to do that, but not always required. It is
worthwhile to benchmark and experiment.
Stencil
Instead of manually iterating over a multidimensional array and applying a function to each element, while reading its neighboring elements (as you would do in an imperative language) in a functional language it is much more efficient to apply a stencil function and let the library take care of all of bounds checking and iterating in a cache friendly manner.
What’s a stencil? It is a declarative way of
specifying a pattern for how elements of an array in a neighborhood will be used in order to update
each element of the newly created array. In massiv a Stencil
is a function that can read the
neighboring elements of the stencil’s center (the zero index), and only those, and then outputs a
new value for the center element.
Let’s create a simple, but somewhat meaningful array and create an averaging stencil. There is nothing special about the array itself, but the averaging filter is a stencil that sums the elements in a Moore neighborhood and divides the result by 9, i.e. finds the average of a 3 by 3 square.
arrLightIx2 :: Comp > Sz Ix2 > Array D Ix2 Double
arrLightIx2 comp arrSz = makeArray comp arrSz $ \ (i :. j) > sin (fromIntegral (i * i + j * j))
{# INLINE arrLightIx2 #}
average3x3Filter :: Fractional a => Stencil Ix2 a a
average3x3Filter = makeStencil (Sz (3 :. 3)) (1 :. 1) $ \ get >
( get (1 :. 1) + get (1 :. 0) + get (1 :. 1) +
get ( 0 :. 1) + get ( 0 :. 0) + get ( 0 :. 1) +
get ( 1 :. 1) + get ( 1 :. 0) + get ( 1 :. 1) ) / 9
{# INLINE average3x3Filter #}
Here is what it would look like in GHCi. We create a delayed array with some funky periodic function, and make sure it is computed prior to mapping an average stencil over it:
λ> arr = computeAs U $ arrLightIx2 Par (Sz (600 :. 800))
λ> :t arr
arr :: Array U Ix2 Double
λ> :t mapStencil Edge average3x3Filter arr
mapStencil Edge average3x3Filter arr :: Array DW Ix2 Double
As you can see, that operation produced an array of the earlier mentioned representation Delayed
Windowed DW
. In its essence DW
is an array type that does no bounds checking in order to gain
performance, except when it’s near the border, where it uses a border resolution technique supplied
by the user (Edge
in the example above). Currently it is used only in stencils and not much else
can be done to an array of this type besides further computing it into a manifest representation.
This example will be continued in the next section, but before that I would like to mention that
some might notice that it looks very much like convolution, and in fact convolution can be
implemented with a stencil. There is a helper function makeConvolutionStencil
that lets
you do just that. For the sake of example we’ll do a sum of all neighbors by hand instead:
sum3x3Filter :: Fractional a => Stencil Ix2 a a
sum3x3Filter = makeConvolutionStencil (Sz (3 :. 3)) (1 :. 1) $ \ get >
get (1 :. 1) 1 . get (1 :. 0) 1 . get (1 :. 1) 1 .
get ( 0 :. 1) 1 . get ( 0 :. 0) 1 . get ( 0 :. 1) 1 .
get ( 1 :. 1) 1 . get ( 1 :. 0) 1 . get ( 1 :. 1) 1
{# INLINE sum3x3Filter #}
There is not a single plus or multiplication sign, that is because convolutions is actually
summation of elements multiplied by a kernel element, so instead we have composition of functions
applied to an offset index and a multiplier. After we map that stencil, we can further divide each
element of the array by 9 in order to get the average. Yeah, I lied a bit, Array DW ix
is an
instance of Functor
class, so we can map functions over it, which will be fused as with a regular
D
elayed array:
computeAs U $ fmap (/9) $ mapStencil Edge sum3x3Filter arr
If you are still confused of what a stencil is, but you are familiar with Conway’s Game of
Life this should hopefully clarify it a
bit more. The function life
below is a single iteration of Game of Life:
lifeRules :: Word8 > Word8 > Word8
lifeRules 0 3 = 1
lifeRules 1 2 = 1
lifeRules 1 3 = 1
lifeRules _ _ = 0
lifeStencil :: Stencil Ix2 Word8 Word8
lifeStencil = makeStencil (Sz (3 :. 3)) (1 :. 1) $ \ get >
lifeRules (get (0 :. 0)) $ get (1 :. 1) + get (1 :. 0) + get (1 :. 1) +
get ( 0 :. 1) + get ( 0 :. 1) +
get ( 1 :. 1) + get ( 1 :. 0) + get ( 1 :. 1)
life :: Array S Ix2 Word8 > Array S Ix2 Word8
life = compute . mapStencil Wrap lifeStencil
The full working example that uses GLUT and OpenGL is located in GameOfLife. You can run it if you have the GLUT dependencies installed:
$ cd massivexamples && stack run GameOfLife
massivio
In order to do anything useful with arrays we often need to be able to read some data from a file. Considering that most common arraylike files are images, massivio provides an interface to read, write and display images in common formats using Haskell native JuicyPixels and Netpbm packages.
Color package provides a variety of color spaces and conversions
between them, which are used by massivio
package as pixels during reading and writing images.
An earlier example wasn’t particularly interesting, since we couldn’t visualize what is actually going on, so let’s expand on it:
import Data.Massiv.Array
import Data.Massiv.Array.IO
main :: IO ()
main = do
let arr = computeAs S $ arrLightIx2 Par (600 :. 800)
toImage ::
(Functor (Array r Ix2), Load r Ix2 (Pixel (Y' SRGB) Word8))
=> Array r Ix2 Double
> Image S (Y' SRGB) Word8
toImage = computeAs S . fmap (PixelY' . toWord8)
lightPath = "files/light.png"
lightImage = toImage $ delay arr
lightAvgPath = "files/light_avg.png"
lightAvgImage = toImage $ mapStencil Edge (avgStencil 3) arr
lightSumPath = "files/light_sum.png"
lightSumImage = toImage $ mapStencil Edge (sumStencil 3) arr
writeImage lightPath lightImage
putStrLn $ "written: " ++ lightPath
writeImage lightAvgPath lightAvgImage
putStrLn $ "written: " ++ lightAvgPath
writeImage lightSumPath lightSumImage
putStrLn $ "written: " ++ lightSumPath
displayImageUsing defaultViewer True . computeAs S
=<< concatM 1 [lightAvgImage, lightImage, lightSumImage]
massivexamples/vision/files/light.png
:
massivexamples/vision/files/light_avg.png
:
The full example is in the example vision package and if you
have stack
installed you can run it as:
$ cd massivexamples && stack run avgsum
Other libraries
A natural question might come to mind: Why even bother with a new array library when we already have a few really good ones in the Haskell world? The main reasons for me are performance and usability. I personally felt like there was much room for improvement before I even started working on this package, and it seems like it turned out to be true. For example, the most common goto library for dealing with multidimensional arrays and parallel computation used to be Repa, which I personally was a big fan of for quite some time, to the point that I even wrote a Haskell Image Processing library based on top of it.
Here is a quick summary of how massiv
is better than Repa
:
 It is actively maintained.
 Much more sophisticated scheduler. It is resumable and is capable of handling nested parallel computation.
 Improved indexing data types.
 Safe stencils for arbitrary dimensions, not only 2D convolution. Stencils are composable
 Improved performance on almost all operations.
 Structural parallel folds (i.e. left/right  direction is preserved)
 Super easy slicing.
 Extensive mutable interface
 More fusion capabilities with delayed stream and push array representations.
 Delayed arrays aren’t indexable, only Manifest are (saving user from common pitfall in Repa of trying to read elements of delayed array)
As far as usability of the library goes, it is very subjective, thus I’ll let you be a judge of that. When talking about performance it is the facts that do matter. Thus, let’s not continue this discussion in pure abstract words, below is a glimpse into benchmarks against Repa library running with GHC 8.8.4 on Intel® Core™ i73740QM CPU @ 2.70GHz × 8
benchmarking Repa/MxM U Double  (500x800 X 800x500)/Par
time 120.5 ms (115.0 ms .. 127.2 ms)
0.998 R² (0.996 R² .. 1.000 R²)
mean 124.1 ms (121.2 ms .. 127.3 ms)
std dev 5.212 ms (2.422 ms .. 6.620 ms)
variance introduced by outliers: 11% (moderately inflated)
benchmarking Massiv/MxM U Double  (500x800 X 800x500)/Par
time 41.46 ms (40.67 ms .. 42.45 ms)
0.998 R² (0.994 R² .. 0.999 R²)
mean 38.45 ms (37.22 ms .. 39.68 ms)
std dev 2.342 ms (1.769 ms .. 3.010 ms)
variance introduced by outliers: 19% (moderately inflated)
benchmarking Sobel/Par/Operator  Repa
time 17.82 ms (17.30 ms .. 18.32 ms)
0.997 R² (0.994 R² .. 0.998 R²)
mean 17.42 ms (17.21 ms .. 17.69 ms)
std dev 593.0 μs (478.1 μs .. 767.5 μs)
variance introduced by outliers: 12% (moderately inflated)
benchmarking Sobel/Par/Operator  Massiv
time 7.421 ms (7.230 ms .. 7.619 ms)
0.994 R² (0.991 R² .. 0.997 R²)
mean 7.537 ms (7.422 ms .. 7.635 ms)
std dev 334.3 μs (281.3 μs .. 389.9 μs)
variance introduced by outliers: 20% (moderately inflated)
Sum all elements of a 2D array:
benchmarking Sum/Seq/Repa
time 539.7 ms (523.2 ms .. 547.9 ms)
1.000 R² (1.000 R² .. 1.000 R²)
mean 540.1 ms (535.7 ms .. 543.2 ms)
std dev 4.727 ms (2.208 ms .. 6.609 ms)
variance introduced by outliers: 19% (moderately inflated)
benchmarking Sum/Seq/Vector
time 16.95 ms (16.78 ms .. 17.07 ms)
0.999 R² (0.998 R² .. 1.000 R²)
mean 17.23 ms (17.13 ms .. 17.43 ms)
std dev 331.4 μs (174.1 μs .. 490.0 μs)
benchmarking Sum/Seq/Massiv
time 16.78 ms (16.71 ms .. 16.85 ms)
1.000 R² (1.000 R² .. 1.000 R²)
mean 16.80 ms (16.76 ms .. 16.88 ms)
std dev 127.8 μs (89.95 μs .. 186.2 μs)
benchmarking Sum/Par/Repa
time 81.76 ms (78.52 ms .. 84.37 ms)
0.997 R² (0.990 R² .. 1.000 R²)
mean 79.20 ms (78.03 ms .. 80.91 ms)
std dev 2.613 ms (1.565 ms .. 3.736 ms)
benchmarking Sum/Par/Massiv
time 8.102 ms (7.971 ms .. 8.216 ms)
0.999 R² (0.998 R² .. 1.000 R²)
mean 7.967 ms (7.852 ms .. 8.028 ms)
std dev 236.4 μs (168.4 μs .. 343.2 μs)
variance introduced by outliers: 11% (moderately inflated)
Here is also a blog post that compares Performance of Haskell Array libraries through Canny edge detection
Further resources on learning massiv
:
 2021  Haskell eXchange  Multidimensional Arrays that Do Not Exist
 2019  Monadic Party  Haskell arrays with Massiv
 2018  Monadic Warsaw #14  Haskell arrays that are easy and fast
Changes
1.0.4
 Improve performance of sorting algorithm and its parallelization. Fix huge slow down on CPUs with at least 16 cores.
1.0.3
 Deprecated
indexWith
in favor ofindexAssert
 Addition of scans:
sscanl
,sscanl1
,sprescanl
,spostscanl
andspostscanlAcc
 Expose
unsafePrefIndex
1.0.2
 Addition of
Iterator
type class and related fucntions: Addition of
RowMajor
,RowMajorLinear
andRowMajorUnbalanced
iterators.  Switch parallel left fold to new iterator
 Addition of
 Improvements to functions that do the looping:
 Addition of
loopNextA_
andloopNextM
 Deprecate
loopM_
in favor ofloopA_
 Addition of
loopA
andloopF
for applicative iterators  Addition of
iloopA_
andiloopM
 Addition of
nextMaybeF
 Addition of
iterLinearST_
,iterLinearAccST_
anditerLinearAccST
 Addition of an optimized
scheduleMassivWork
for internal use  Addition of a new workhorse:
splitWorkWithFactorST
 Addition of a new workhorse:
splitWorkWithFactorST
 Addition of
 Changes to
Index
class: Deprecate
iterM_
in favor ofiterA_
 Adititon of sequential iterators:
iterTargetRowMajorA_
,iterTargetRowMajorAccM
needed forRowMajor
iterator  Addition of parallelizable iterators:
iterRowMajorST
,iterTargetRowMajorAccST
,iterTargetRowMajorAccST_
needed forRowMajor
iterator  Addition of
iterF
for using with applicative iterators.  Addition of
stepNextMF
for streaming iteration of multidimensional arrays.
 Deprecate
 Addition of
repr
.  Addition of
quicksortAs
,quicksortAsBy
,quicksortAsByM
 Fix backwards compatibility with ghc8.0
 Get rid of dependency on
genvalidity
: too many compatibility issues for little gain  Introduce
PrefIndex
andunsafePrefIndex
: a preference when indexing into multidimensionalSource
arrays. Adopt it where possible for left and right folds, traversals, but not zipping  Improve multidimensional indices for streams. Improve
steps
andisteps
 Get rid of build warnings for ghc9.4
 Make
Monoid
andMonad
instances forward compatible
 Make
 Compatibility with
vector0.13
: Fix
Unbox
instance forIxN
 Fix safety of boxed vector conversion:
toBoxedVector
/fromBoxedVector
 Fix
 Reexport Manifest realetd functions from
Data.Massiv.Array.Manifest
as a migration strategy for the move in the next minor version bump.
1.0.1
 Relax constraint on
computeInto
by removing requirement forSize
 Fix
BL
, which due to a forgottenseq
was not lazy.
1.0.0
 Addition of
sumArrays'
,sumArraysM
andproductArrays'
,productArraysM
.  Remove
Num
/Fractional
/Floating
instances forD
andDI
arrays. This was done to prevent surprises as in: #97  Remove helper class
Nested
and type familyNestedStuct
 Make
negate
inNum
instance throw error forSz
in order to avoid surprising behavior reported in: #114  Add of
munsafeResize
 Add
uniformArray
anduniformRangeArray
 Replace
isNonEmpty
withisNotZeroSz
and addedisZeroSz
 Consolidate
Construct
class intoLoad
 Introduce
Shape
, the parent ofSize
 Move
size
fromLoad
into new classSize
 Consolidate
Resize
intoSize
 Removed
maxSize
and replaced it withmaxLinearSize
 Remove specialized
DW
instances that used tuples as indices.  Get rid of
M
representation  Remove
R
type family andSlice
,InnerSlice
andExtract
classes in favor ofD
.  Consolidate
OuterSlice
intoSource
 Add
Strategy
and movesetComp
(fromConstruct
) andgetComp
(fromLoad
) in there.  Remove
ix
fromMutable
,Manifest
,Source
 Remove
liftArray2
. Instead addliftArray2'
andliftArray2M
that don’t behave like amap
for singleton argument.  Expose
liftNumArray2M
 Prevent
showsArrayPrec
from changing index type  Change function argument to monadic action for
unstablePartitionM
andunsafeUnstablePartitionM
 Replace
snull
with a more genericisNull
 Switch
DL
loading function to run inST
monad, rather than in anyMonad m
.  Rename
msize
>sizeOfMArray
 Add
unsafeResizeMArray
andunsafeLinearSliceMArray
 Rename:
loadArrayM
>iterArrayLinearM_
loadArrayWithSetM
>iterArrayLinearWithSetM_
.loadArrayWithStrideM
>iterArrayLinearWithStrideM_
.
 Add
iterArrayLinearST_
anditerArrayLinearWithSetST_
toLoad
class instead ofloadArrayM
andloadArrayWithSetM
.  Add
iterArrayLinearWithStrideST_
toLoadStride
class instead ofloadArrayWithStrideM
.  Add new mutable functions:
resizeMArrayM
andflattenMArray
,outerSliceMArrayM
andouterSlicesMArray
,for2PrimM_
andifor2PrimM_
,zipSwapM_
 Switch effectful mapping functions to use the representation specific
iteration. This means that they are now restricted to
Load
instead ofSource
. Functions affected:mapIO_
,imapIO_
,forIO_
andiforIO_
mapIO
,imapIO
,forIO
andiforIO
 Add
Uniform
,UniformRange
andRandom
instances forIx2
,IxN
,Dim
,Sz
andStride
 Consolidate
Mutable
intoManifest
type class and move theMArray
data family outside of the class.  Make sure empty arrays are always equal, regardless of their size.
 Remove
LN
representation in favor of a standaloneList
newtype wrapper around lists.
0.6.1
 Addition of
withLoadMArray_
,withLoadMArrayS
,withLoadMArrayS_
,withLoadMArrayST
,withLoadMArrayST_
 Addition of
replaceSlice
andreplaceOuterSlice
 Addition of
quicksortBy
,quicksortByM
andquicksortByM_
 Fix performance regression for
quicksort
andquicksortM_
introduced in previous release.
0.6.0
 Fix semantics of
Applicative
,Num
andFractional
instance forD
arrays: mismatched sizes will throw an error.  20% speed improvement of matrix multiplication:
multiplyMatrices
,.><.
and!><!
. Type signature has changed toMutable
for both arguments, thus it’s a breaking change.  Switch
><.
and><!
from returning a delayed array to mutable, since that’s whatmultiplyVectorByMatrix
returns.  Addition of synonym
HighIxN
and removing redundant1 <= n
constraint.  Deprecating
makeStencilDef
,unsafeMapStencil
and fix dangers of invalid stencils reading out of bounds. Get rid ofValue
. Fix for #109.  Addition of
appComp
 Addition of
mkSzM
 Addition of
SizeOverflowException
andSizeNegativeException
 Fix setting computation for boxed vector when converted with
fromVectorM
andfromVector'
 Add computation strategy argument to
fromUnboxedVector
, just so it matches other vector conversion functions.  Removed
defaultElement
 Removed deprecated functions:
#>
,*
,multiplyTransposed
,fromIntegerA
,fromRationalA
,piA
 Addition of
BL
representation and related functionality, fix for #111. Addition of functions:
wrapLazyArray
,unwrapLazyArray
,toLazyArray
,evalLazyArray
,forceLazyArray
,unwrapMutableLazyArray
,fromBoxedVector
,fromBoxedMVector
.  Rename:
unsafeNormalBoxedArray
>coerceNormalBoxedArray
unsafeBoxedArray
>coerceBoxedArray
 Remove
unsafeFromBoxedVector
 Conversion from vector with
castFromVector
will returnBL
representation for boxed vector  Change type
B
>BL
for functions:toBoxedVector
andtoBoxedMVector
 Addition of functions:
 Rename
N
>BN
and add backwards compatibility shim.  Make
replicate
a function inConstruct
class  Add
newMArray
,newMArray'
and deprecatenew
 Add custom implementation for
<$
inFunctor
instances forBL
andB
.
0.5.9
 Add
mallocCompute
,mallocCopy
andunsafeMallocMArray
 Fix
.><.
,><.
and.><
on empty matrices. Result is now guaranteed to be empty too.  Add
unwrapByteArrayOffset
andunwrapMutableByteArrayOffset
 Add
fromByteArrayOffsetM
andfromMutableByteArrayOffsetM
0.5.8
 Improve loading of push arrays by adding
loadArrayWithSetM
and deprecatingdefaultElement
.
0.5.9
 Add
mallocCompute
,mallocCopy
andunsafeMallocMArray
0.5.8
 Improve loading of push arrays by adding
loadArrayWithSetM
and deprecatingdefaultElement
.
0.5.7
 Improve performance of
><.
and><!
while making their constraints a bit more relaxed.  Expose
unsafeLoadIntoM
andunsafeLoadIntoS
 Expose
eqArrays
andcompareArrays
 Add
multiplyMatrixByVector
andmultiplyVectorByMatrix
0.5.6
 Fix
(.)
(it was incorrectly implemented as a flip of(.)
 Addition of numeric functions:
 Partial:
!+!
,!!
,!*!
,!/!
 Reciprocal division
/.
 More efficient matrixmatrix multiplication:
.><.
and!><!
(also helpersmultiplyMatrices
andmultiplyMatricesTransposed
)  More efficient matrixvector multiplication:
.><
and!><
 New vectormatrix multiplication:
><.
and><!
 Dot product
dotM
and!.!
 Norm
normL2
 Partial:
 Deprecated
*
and#>
0.5.5
 Add
takeWhile
,dropWhile
andfindIndex
 Improve performance of
any
,and
,or
,all
 Add
elem
0.5.4
 Addition of
unsafeTransformStencil
 Add
zip4
,unzip4
,zipWith4
andizipWith4
 Make
Resize
a superclass ofSource
 Addition of
outerSlices
,innerSlices
,withinSlices
andwithinSlicesM
 Addition of
stackSlicesM
,stackOuterSlicesM
andstackInnerSlicesM
 Addition of
computeP
 Fix perfomrmance issue of folding functions applied to arrays with
Seq
computation strategy.
0.5.3
 Fix
tanA
andtanhA
. #96  Relax argument of
snoc
andcons
constraint toLoad
vectors  Improve
unsnocM
andunconsM
by switching tounsafeLinearSlice
, instead of delaying the array.  Fix parallelization for windowed array when computed with stride
 Fix massiv doctests not being able to find massiv.h under NixOS
0.5.2
 Addition of
lowerTriangular
andupperTriangular
 Relax
identityMatrix
type to return an array of anyNum
type, not justInt
.  Addition of
unsafeMakeLoadArrayAdjusted
 Add matrixvector product (
(#>)
)  Addition of
siterate
0.5.1
 Fix
sfromListN
accepting a plainInt
instead ofSz1
, as well as switch to upper bound.  Fix order of argumetns in
iforM
 Restrict
szip*
,szipWith*
andsizipWith*
functions to flat vectors.  Addition of
unsafeSUnfoldrN
,unsafeSUnfoldrNM
andunsafeSFromListN
 Fix
sunfoldrN
,sunfoldrNM
andsfromListN
to not trust the supplied size.  Move
isEmpty
intoLoad
class  Add
isNotEmpty
0.5.0
 Remove
Show
instance fromValue
.  Addition of
unsafeCreateArray
,unsafeCreateArray_
andunsafeCreateArrayS
 Remove
Comp
argument from functions that ignore it and set it toSeq
:createArrayS_
,createArrayS
,createArrayST_
,createArrayST
unfoldrPrimM_
,iunfoldrPrimM_
,unfoldrPrimM
,iunfoldrPrimM
unfoldlPrimM_
,iunfoldlPrimM_
,unfoldlPrimM
,iunfoldlPrimM
 Addition of
fromStorableVector
andfromStorableMVector
 Modify
toMutableByteArray
to produce a copy if dealing with slice.  Addition of
toByteArrayM
,toMutableByteArrayM
 Change
replicate
to produce delayed load arrayDL
 Export unsafe stencil functions from
Data.Array.Massiv.Unsafe
, rather than fromData.Massiv.Array.Stencil.Unsafe
.  Implement
unsafeMapStencil
and deprecatemapStencilUnsafe
andforStencilUnsafe
 Addition of
castToBuilder
 Addition of conversion functions:
unwrapNormalForm
andevalNormalForm
toBoxedVector
,toBoxedMVector
,evalBoxedVector
andevalBoxedMVector
unwrapByteArray
andunwrapMutableByteArray
toPrimitiveVector
,toPrimitiveMVector
,fromPrimitiveVector
andfromPrimitiveMVector
toStorableVector
,toStorableMVector
,fromStorableVector
andfromStorableMVector
fromUnboxedVector
andfromUnboxedMVector
unsafeBoxedArray
,unsafeNormalBoxedArray
,unsafeFromBoxedVector
 Removed deprecated
traverseAR
,itraverseAR
,traversePrimR
anditraversePrimR
 Removed:
imapMR
,imapMR
,iforMR
, andiforMR
 Renamed:
withMArray
towithMArray_
,withMArrayS
towithMArrayS_
andwithMArrayST
towithMArrayST_
 Added versions that keep the artifact of mutable action:
withMArray
,withMArrayS
,withMArrayST
.
0.4.5
 Addition of
computeIO
andcomputePrimM
 Addition of
makeArrayLinearA
 Addition of
traverseS
 Fix regression in performance introduced in
massiv0.4.0
0.4.4
 Addition of
appendOuterM
andconcatOuterM
 Addition of
zoom
 Addition of
write_
,modify_
andswap_
0.4.3
 Addition of
catMaybesS
andtally
0.4.3
 Addition of
applyStencil
andPadding
with helper functionsnoPadding
andsamePadding
.  Addition of
foldlStencil
,foldrStencil
and monoidalfoldStencil
.  Addition of common generic stencils:
sumStencil
,productStencil
,avgStencil
,maxStencil
,minStencil
andidStencil
.  Addition of
mapStencilUnsafe
for the brave.  Improve compile time error reporting for invalid dimensions.
 Fix incorrect loading of
DW
arrays of dimension higher than 3  Addition of
foldOuterSlice
,ifoldOuterSlice
,foldInnerSlice
andifoldInnerSlice
. Fix for #56
0.4.2
 Fix loading empty
DS
stream arrays of unknown size. Fix for #83.
0.4.1
 Introduction of
Stream
andDS
representation:filterS
,filterM
,ifilterS
,ifilterM
mapMaybeS
,mapMaybeM
,imapMaybeS
,imapMaybeM
unfoldr
,unfoldrN
takeS
anddropS
 Deprecated
traverseAR
,itraverseAR
,traversePrimR
,itraversePrimR
(not feasible to keep duplicate functions just for representation,TypeApplications
orScopedVariables
should be used instead.)  Fix performance issue with copying of unboxed arrays and initialization of storable array.
 Addition of
unsafeLoadIntoS
,unsafeLoadInto
andmaxSize
 Addition of
reverse
,reverse'
andreverseM
 Addition of
modifyDimension
,modifyDimM
, andmodifyDim'
0.4.0
 Made
Construct
a super class ofMutable
 Reimplement a safe version of
makeLoadArray
, that is parallelizable.  Switch from
EltRepr r ix
to much simplerR r
 Remove
Construct
instance forM
representation. unsafeLinearSet
 length argument now acceptsSz1
instead of anInt
 Renamed:
forPrimM_
>forPrimM
iforPrimM_
>iforPrimM
iforLinearPrimM_
>iforLinearPrimM
 Introduced new functions that do not mutate the original array:
forPrimM_
,iforPrimM_
andiforLinearPrimM_
 Addition of
readM
,writeM
,modifyM
,swapM
,modifyM_
,swapM_
 Add an orphan instance of
MonadThrow
forST
monad for older versions ofexceptions
. See ekmett/exceptions#72  Deprecation of
read'
,write'
modify'
andswap'
 Make
modify
accept a monadic action, rather than a pure function. Also now it returns the old element.  Make
swap
return the swapped elements.  Addition of
unsafeLinearSwap
andunsafeSwap
 Expose
unsafeLinearModify
andunsafeModify
 Expose
Data.Massiv.Core.List
 Expose
indexWith
, so macroINDEX_CHECK
frommassiv.h
could be used outside massiv.  Addition of
liftSz
 Fixed
expand*
functions by making them acceptSz1
instead of anInt
 Addition of
expandWithinM
 Bunch of minor fixes to
Show
instances  Extracted testsuite into it’s own package.
 Stop accepting computation strategy for all functions that can be performed sequentially only:
iterateN
iiterateN
unfoldrS_
iunfoldrS_
unfoldlS_
iunfoldlS_
makeArrayA
makeArrayAR
generateArrayLinearS
generateArrayS
 Redefined most of the numeric operators with
Numeric
andNumericFloat
. Will be required for SIMD operations. Num
,Fractional
andApplicative
forD
andDI
changed behavior: instead of treating singleton as a special array of any size it is treated as singleton.
0.3.6
 Addition of
unsafeArrayLinearCopy
,unsafeLinearCopy
,unsafeLinearShrink
,unsafeLinearGrow
 Implementation of
iterateUntil
anditerateUntilM
identityMatrix
 generation of identity matrix
0.3.5
 Fix and export
guardNumberOfElements
Eq
instances forIndexException
andSizeException
 Fix
upsample
implementation and improve its performance.  Addition of
deleteRegionM
,deleteRowsM
anddeleteColumnsM
0.3.4
 Use the the new stateful workers feature of
scheduler1.4.0
 Addition of:
randomArrayS
randomArrayWS
generateArrayWS
generateArrayLinearWS
mapWS
,forWS
,imapWS
andiforWS
 and
splitLinearlyWithStatefulM_
0.3.3
 Fix type signature for
createArray
.  Support for new version of
scheduler
 Addition of
randomArray
0.3.2.1
 Fix
sqrtA
function: #76
0.3.2
 Exported
withMArrayS
 Switch to pure exception throwing for
read'
,write'
,modify'
andswap'
.MonadThrow
constraint prevented those functions to be used inST
monad.  Addition of
quicksort
,quicksortM_
,unstablePartitionRegionM
andunsafeUnstablePartitionRegionM
0.3.1
 Addition of
rangeStepInclusive'
 Addition of
flatten
makeLoadArray
has been deprecated intounsafeMakeLoadArray
. A new safe
makeLoadArrayS
has been added.  Fix
infix 4
for(...)
and(..:)
range functions, so they can be easily composed with numeric operations  Addition of
imapSchedulerM_
andiforSchedulerM_
0.3.0
 Class hierarchy an associated methods:
getComp
moved fromConstruct
toLoad
Size
class lost array value parametere
.unsafeResize
andunsafeExtract
became their own classes
 New classes:
Resize
withunsafeResize
from oldSize
, except witharray
type parameter for applicability to mutableMArray
sExtract
withunsafeExtract
from oldSize
StrideLoad
, child ofLoad
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 fromData.Foldable
takes no arguments and requires elements to be a monoidsingleton
does not accept computation strategy any more and createsSeq
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'
andswap'
now live in IO and throw proper exceptions. loadArray
is renamed toloadArrayM
and there is a new separate function (not part ofLoad
class) with the nameloadArray
that actually usesloadArrayM
 Moved
unsafeWithPtr
intoData.Massiv.Array.Unsafe
 Addition of:
unsafeArrayToForeignPtr
,unsafeMArrayToForeignPtr
,unsafeArrayFromForeignPtr
,unsafeArrayFromForeignPtr0
,unsafeMArrayFromForeignPtr
,unsafeMArrayFromForeignPtr0
 Addition of
castToByteString
,castFromByteString
 Addition of
makeUnsafeStencil
Window
now has anwindowUnrollIx2
field. Addition of
insertWindow
anddropWindow
0.2.8.1
 Fix
sqrtA
function. Backport of #76
0.2.8
 Fixed a problem where convolution stencil size was not inverted, causing out of bounds memory read: #72
 Fixed an issue with windowed array where a stencil size is smaller than the array it is applied to
 Fixed incorrect crosscorrelation stencil construction
0.2.7
 Fixed a serious performance regression in
Stencil
’sFunctor
instance, which was introduced in version0.2.3
 Added type and pattern synonyms
Sz
for future compatibility with version0.3
. Could be useful for migration.
0.2.6
 Add
expand*
family of functions.  Long awaited
makeArrayM
/makeArrayA
andmapM
/forM
/imapM
/iforM
/traverseA
/itraverseA
alnog with corresponding functions allowing for supplying representation.  Deprecate
mapP
andmapP_
in favor ofmapIO
andmapIO_
, while making latter respect theComp
.  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
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
andfoldrInner
 Addition of functions that can fold over any dimension (
foldlWithin
,foldlWithin'
, etc.)  Addition of
ifoldMono
andifoldSemi
, thus fixing: #54  Improvement over manipulating index dimensions with addition of type level
Dimension n
data type and functions likegetDimension
,dropDimension
.  Addition of
insertDim
and type levelinsertDimension
as well aspullOutDim
andpullOutDimension
 Add partial
extractFromTo'
0.2.3
 Addition of
Profunctor
functions forStencil
:lmapStencil
,rmapStencil
andbimapStencil
 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 slightly 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 functionscomputeWithStride
andcomputeWithStrideAs
. 
Addition of
Window

Addition of
loadArray
adnloadArrayWithStride
with default implementations that will become new loading functions in a subsequent release.loadArray
will replaceloadS
andloadP
, which will be deprecated in the next release and removed in the next major release. Some of this is discussed in #41 
Addition of various conversion functions:
fromByteString
,toByteString
andtoBuilder
unwrapArray
,evalArray
,unwrapMutableArray
,evalMutableArray
unwrapNormalFormArray
,evalNormalFormArray
,unwrapNormalFormMutableArray
,evalNormalFormMutableArray

Fix:
Eq
instance forArray M ix e
0.2.0
 Fixed type signatures for
convertAs
andconvertProxy
 Added type constructors for
DW
andDI
Show
instance forDW
arrays. Addition of
unsafeBackpermuteDW
.  Breaking changes:
 Create new
Data.Massiv.Array.Stencil.Unsafe
module and moveforStencilUnsafe
into it.  Rename of rank > dimensions #25
 Removal
Eq
andOrd
instances forValue
#19  Move border resolution to
mapStencil
frommakeStencil
.
 Removal
 Updated iterators
iterM
,iterM_
, etc. to have a separate step per dimension.
 Create new
0.1.6
Semigroup
andMonoid
instance forValue
. Addition of
forStencilUnsafe
.  Fix
minimum
behaving asmaximum
.  Addition of
foldSemi
.
0.1.5
 Fix inverted stencil index calculation #12
 Add support for crosscorrelation.
0.1.4
 Addition of Monoidal folding
foldMono
.  Expose
liftArray2
.
0.1.3
 Addition of
withPtr
andunsafeWithPtr
for Storable arrays  Addition of
computeInto
.  Exposed
makeWindowedArray
.
0.1.2
 Support for GHC8.4  instance of
Comp
forSemigroup
 Brought back support for GHC7.10
0.1.1
 Addition of experimental
mapM
,imapM
,forM
,iforM
,generateM
andgenerateLinearM
functions. Fixes #5  Addition of
Ord
instances for some array representations.
0.1.0
 Initial Release