# Multiply vector elementwise by \[1, v, v, ...\]

**URL:** <https://discourse.julialang.org/t/multiply-vector-elementwise-by-1-v-v/129442>\
**Category:** General Usage\
**Tags:** question\
**Created:** [May 29, 2025, 2:42pm UTC](https://discourse.julialang.org/t/multiply-vector-elementwise-by-1-v-v/129442 "2025-05-29T14:42:38Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [May 29, 2025, 2:42pm UTC](https://discourse.julialang.org/t/multiply-vector-elementwise-by-1-v-v/129442/1 "2025-05-29T14:42:38Z")

</div>

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

```julia
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

```julia
map(*, s, a)

```

works fine, but I want to hook into the broadcasting machinery.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [May 29, 2025, 2:58pm UTC](https://discourse.julialang.org/t/multiply-vector-elementwise-by-1-v-v/129442/2 "2025-05-29T14:58:21Z")

</div>

The way to do this is to add `BroadcastStyle`, and `Size` trait methods that detect the presence of that `SOneTo` that comes from `axes(::SVector)`:

```julia
StaticArrays.Size(::AfterOne{T, SOneTo{N}}) where {T, N} = Size{(N,)}()
Base.Broadcast.BroadcastStyle(::Type{AfterOne{T, SOneTo{N}}}) where {T, N} = StaticArrays.StaticArrayStyle{1}()

```

and then voila

```julia-repl
julia> z = a .* s
3-element SVector{3, Float64} with indices SOneTo(3):
  1.0
  9.0
 15.0

```

Overloading `Size` is documented, but `StaticArrayStyle` unfortunately isn’t so maybe we should open an issue for that.

---

<div class="post-metadata">

**Author:** ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)\
**Post date:** [May 29, 2025, 3:28pm UTC](https://discourse.julialang.org/t/multiply-vector-elementwise-by-1-v-v/129442/3 "2025-05-29T15:28:22Z")

</div>

Note that `SA[1,2,3] .* fill!(similar(SA[1,2,3]), 1)` makes an MVector but returns an SVector. Which suggests doing this:

```julia
julia> function mulafter(x::AbstractVector, v::Number)
         y = fill!(similar(x), v)
         y[begin: begin] .= 1
         x .* y
       end;

julia> mulafter([1,2,3], 4)
3-element Vector{Int64}:
  1
  8
 12

julia> @btime mulafter($(SA[1,2,3]), 4) # MVector does not escape
  2.416 ns (0 allocations: 0 bytes)
3-element SVector{3, Int64} with indices SOneTo(3):
  1
  8
 12

```

Could be more careful about promoting eltypes. Allocates two vectors not one for `Array` case. But much simpler than defining & testing an array struct.
