How to mutate static arrays?

question
array

#1

From the README:

The package provides a range of different useful built-in StaticArray types, which include mutable and immutable arrays based upon tuples, arrays based upon structs, and wrappers of Array. There is a relatively simple interface for creating your own, custom StaticArray types, too.

I tried I to mutate a simple SVector, but there is no setindex! defined for it:

using StaticArrays

v = @SVector [1,2,3]
v[1] = 0
julia> v[1] = 0

ERROR: setindex!(::SVector{3,Int64}, value, ::Int) is not defined.
Stacktrace:
 [1] setindex!(::SVector{3,Int64}, ::Int64, ::Int64) at /home/juliohm/.julia/v0.6/StaticArrays/src/indexing.jl:3

#2

SVector is immutable. If you want a mutable container, you need an MVector


#3

There is actually a setindex method for SVectors. It’s not in-place, but replaces the entire vector (note the absense of a !).

For short vectors setindex(::SVector, val, ind) has similar performance to setindex!(::MVector, ...), but as the vector lengths grow performance degrades.

Try it out:

v = @SVector [1,2,3]
v = setindex(v, 0, 1)

This one is as fast as an MVector, so you can stick to SVectors.


#4

Thank you @DNF, can you advise on the choice between SVector and MVector? What is their different in terms of application?


#5

In my application, these vectors will be of very small length like 3 in most cases. I have a normalization operation that I would like to perform in place, so I picked MVector for now:

"""
    Composition{D}(parts)
A D-part composition as defined by Aitchison 1986.
"""
struct Composition{D}
  parts::MVector{D,Float64}
end

Composition(parts) = Composition{length(parts)}(parts)

"""
Normalize composition `c` in place.
"""
function normalize!(c::Composition)
  p = c.parts
  s = sum(p)
  for i in eachindex(p)
    p[i] /= s
  end
end

#6

Perhaps this helps


#7

If you have many of these points stored in something like a Vector then I would use static vectors and just update in place as a[i] = a[i] / sum(a), where a is the collection of points. Static vectors are stored inline and fetching memory is often a bottleneck in computation heavy code.


#8

The big advantage of SVectors is that they are isbits types, so they can be cheaply allocated on the stack and stored inline in arrays. MVectors are mutable, and thus not isbits, so allocating them is more expensive. MVectors can still be useful, since their fixed size enables lots of specialized algorithms and loop unrolling, but I find that I almost always end up using SVectors in my work.