How to use minimum and maximum for a Vector{SVector{3}}

If I want to determine the smallest values in the rows of A::Matrix it’s as easy as:

min = minimum(A, dims=2)

However, if I have a Vector of SVector{3}'s it’s a bit more complicated. This

using StaticArrays

function test()
    n = 10
    A = [SVector{3}(rand(3)) for i = 1:n]
    min  = minimum(A)
    return min
end

min = test()

Will give me the element of A which has the smallest component instead of comparing all SVector{3}'s and return the smallest 1st, 2nd and 3rd components.

What actually gives me what I want is this:

function test2()
    n = 10
    A = [SVector{3}(rand(3)) for i = 1:n]
    minX = minimum(a[1] for a in A)
    minY = minimum(a[2] for a in A)
    minZ = minimum(a[3] for a in A)
    return SVector{3}(minX, minY, minZ)
end

min = test2()

Is there a more convenient way to do this without calling minimum 3 times? Other than a for loop that is, because test2() and a for-loop generalisation walks through A multiple times.

reduce((x,y) -> min.(x,y), A) does what you want, I think.

3 Likes

You can also get a view of the SVector vector as a matrix:

n = 10
A = [SVector{3}(rand(3)) for i = 1:n]
M = reshape(reinterpret(Float64,A),(3,:))
minimum(M,dims=2)

see https://juliaarrays.github.io/StaticArrays.jl/dev/pages/api/#Arrays-of-static-arrays-1

1 Like

Yup, that does it! Many thanks :slight_smile:

Thanks. I do prefer the conciseness of @stevengj proposal, however.

In addition to being more concise, my reduce((x,y) -> min.(x,y), A) is also about 10× faster on my machine than using reshape, because the reshape technique discards the efficiency of StaticArrays for small-vector operations. It’s also about 3× faster than calling minimum three times, maybe because a single pass over the array has better spatial locality (better cache-line utilization).

4 Likes

I had a gut feeling that it would be faster as well. Thanks for checking :slight_smile: