I have a calculation where I need to multiple various vectors elementwise by [1, v, v, ...].
The inputs may be any kind of vector and I want code to adapt accordingly, ie the input x is an SVector, the output should also be an SVector, without allocations, but if it is a Vector I want a Vector, etc. I also want to spend minimal effort on this and not handle a ton of special cases.
Basically, I want x .* y to yield what it would yield if y was a vector “like” y, filled according to the pattern above.
Inspired by FillArrays.jl, I came up with something like
struct AfterOne{T,A<:AbstractUnitRange} <: AbstractVector{T}
v::T
axis::A
end
AfterOne(v, n::Int) = AfterOne(v, Base.OneTo(n))
Base.axes(a::AfterOne) = (a.axis,)
Base.size(a::AfterOne) = (length(a.axis),)
Base.getindex(a::AfterOne{T}, i) where T = i == firstindex(a.axis) ? one(T) : a.v
using StaticArrays
s = SVector(1, 3, 5.0)
a = AfterOne(3.0, axes(s, 1))
z = a .* s
but z is still not an SVector (it is a SizedVector). How can I fix that? Note that
map(*, s, a)
works fine, but I want to hook into the broadcasting machinery.