binary operations on a StaticArray and Array give outputs with quite-inconsistent types. For example, intuitively SVector .+ Vector should give a SVector rather than a Vector?
I am not sure about this — both options can be reasonable and consistent.
If you want static results, use statically sized decorators (see the docs):
using StaticArrays
a = SVector{3, Float64}(randn(3))
b = SizedVector{3}(randn(3))
a .+ b # 3-element SArray{Tuple{3},Float64,1,3} with indices SOneTo(3)
thanks.
what I mean by inconsistency is some op.(::StaticArray, ::Array) give a StaticArray while other op(). gives Array.
that means we have to test every op(). before knowing the type it gives.
btw, does SizedVector{N}() cause any runtime?
actually, how could I control the output type of generally op.(::A, ::B)? is it about broadcasting? thanks.
seems like I had some confusions about x .+ y vs. x .+ 1.0. To clarify, I try the following:
module Testing
import Base.size, Base.getindex
export A, B
struct A{T <: AbstractVector{Float64} } <: AbstractVector{Float64}
data::T
end
struct B{T <: AbstractVector{Float64} } <: AbstractVector{Float64}
data::T
end
Base.size(x::A) = size(x.data)
Base.size(x::B) = size(x.data)
Base.getindex(x::A, i) = x.data[i]
Base.getindex(x::B, i) = x.data[i]
end
using Main.Testing
a = A(randn(3) )
b = B(randn(3) )
julia> typeof(exp.(a) )
Array{Float64,1}
julia> typeof(a .+ a)
Array{Float64,1}
julia> typeof(a .+ b)
Array{Float64,1}
julia> typeof(b .+ a)
Array{Float64,1}
julia> typeof(a .+ 1.0)
Array{Float64,1}
julia> typeof(b .+ 1.0)
Array{Float64,1}
the last five typeof() results show that, by default, exp.(::A), .+(::A, ::B) and .+(::A, ::Float64)always output a Vector (but not a A nor a B).
So now I know that .+(::SVector, ::Vector) giving a Vector is just the default behavior.
However, there’re important exceptions e.g. exp.(::SVector), .+(::SVector, ::Float64) and .+(::SVector, ::SizedVector): they output SVector but not the default Vector !
How could it be done ? An example making exp.(::A), .+(::A, ::B) and .+(::A, ::Float32) outputting a A is highly appreciated, thanks.
I would agree with that… in an ideal world. The broadcasting machinery is sufficiently intricate that it might not be possible/reasonable though. File an issue?
In some cases wrapping in SizedVector may slow things down since one additional allocation happens (at least in stable versions of Julia).
This should be possible but at the cost of making custom broadcasting in StaticArrays more complicated. It’d have to figure out which arrays should have sizes statically checked and which should have run-time checks.
As far as I understand StaticArrays the general rule is that when all arguments to a broadcast are StaticArrays or scalars (or some wrapped StaticArrays), then SArray will be returned (because it’s the fastest thing). You’ll see it in many other places as well, StaticArrays operations usually return SArray when they can.