I’d like to write generic code that operates on abstract vectors, and is non-allocating. A specific example is a function that subtracts the mean and normalizes a vector. This can be done in-place. However, the problem with writing code that specifically does operations in-place is that it will not work on immutable types, such as SVectors (static vectors from the StaticArrays package).
So I’m having difficulty understanding how I can write such methods that is both efficient and generic.
I have tried the following, hoping the compiler would be smart enough to in-place the operations:
using StaticArrays
mean0(vec) = vec .- (sum(vec) / length(vec))
norm1(vec) = vec .* (1 / sqrt(vec' * vec))
mean0norm1(vec) = norm1(mean0(vec))
function test()
A = SVector{16, Float64}(randn(16))
println(@allocated A = mean0norm1(A))
B = MVector{16, Float64}(randn(16))
println(@allocated B = mean0norm1(B))
C = randn(16)
println(@allocated C = mean0norm1(C))
end
test()
the output of which is:
0
288
384
This shows the compiler won’t get rid of the allocations.
Is there any way around this? It feels like I have to either give up generality, with two code paths, one for mutable and one for immutable objects, or give up on avoiding allocations and having performant code. Is that really the case?