# Generic code for elementwise minimum

I am wondering how to program a generic elementwise minimum of, say, vectors, with the following in mind: the result from an `AbstractVector{T}` is a `T`, eg `SVector` and `Vector` would be preserved.

Data-generating MWE:

``````using StaticArrays
v = [randn(3) for _ in 1:10]           # Vector
s = [SVector(v...) for v in v]         # SVector
m = minimum(reduce(hcat, v); dims = 2) # for testing
``````

Eg for `elementwise_min(v)` I want a `Vector{Float64}`, and for `elementwise_min(s)` an `SArray{Tuple{3},Float64,1,3}`.

1 Like

`min.(v...)` works but is probably a bad idea when `v` is large.

Don’t you want an `SArray{Tuple{10},Float64,1,10}`?
Anyway that would involve getting the `eltype` of your input and, depending on your type, calculating the type parameters (e.g. for the vector of `StaticArrays` the length is not known at compile time and thus the parameter of the resulting static vector is not known).

I don’t think it gets much better than applying a function elementwise and converting the resulting array explicitly with a helper-function, i.e.

``````julia> foo(f,xs) = myconv(eltype(xs),map(f,xs))
myconv(::Type{<:SArray}, xs) = SVector(xs...)
myconv(::Type{<:Array}, xs) = xs
``````

but would be happy to learn otherwise.

This gave me an idea:

``````julia> elementwise_f(f, v) = reduce((x, y) -> f.(x, y), v)
elementwise_f (generic function with 1 method)

julia> elementwise_f(min, v) == m
true

julia> elementwise_f(min, s) == m
true
``````

Thanks!

5 Likes

Why is this a bad idea when `v` is large?

splatting is inefficient for large sizes.

2 Likes

I thought `min.(...)` was broadcasting?

`min.(x, y)` will broadcast `min` over `x` and `y`. `min.(v...)` will first splat `v` into the arguments to `min` and then broadcast over those splatted arguments. It’s the splatting that is extremely inefficient for large sizes.

``````julia> let v = [randn(3) for _ in 1:100]
@btime min.(\$v...)
@btime reduce((x, y) -> min.(x, y), \$v)
end
1.674 ms (33681 allocations: 1.44 MiB)
5.292 μs (99 allocations: 10.83 KiB)
``````
5 Likes

Ah, gotcha. Thanks for the explanation!