# Create SVector with one non-zero value

**URL:** <https://discourse.julialang.org/t/create-svector-with-one-non-zero-value/116295>\
**Category:** General Usage\
**Tags:** type-stability, staticarrays, allocations\
**Created:** [June 27, 2024, 8:17am UTC](https://discourse.julialang.org/t/create-svector-with-one-non-zero-value/116295 "2024-06-27T08:17:46Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Alseidon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alseidon/32/207775_2.png) [@Alseidon](https://discourse.julialang.org/u/Alseidon)\
**Post date:** [June 27, 2024, 8:17am UTC](https://discourse.julialang.org/t/create-svector-with-one-non-zero-value/116295/1 "2024-06-27T08:17:46Z")

</div>

I am trying to define a function `fc(i)` returning a fixed size `SVector` with zeros everywhere, and a 1 at position i. Is it possible to do this with no allocations, and type stability? My first two tries either were type unstable or allocated some memory.

```julia
using StaticArrays

# No allocation, type unstable
fc_unstable(i) = SVector{10, Float64}(
    zeros(SVector{i}),
    vcat(1, zeros(SVector{9-i}))
))

# Type stable, allocates 144 bytes
fc_allocating(i) = SVector{10, Float64}([x == i ? 1 : 0 for x in 1:10])

```

I tried the trick described [here](https://docs.julialang.org/en/v1/manual/types/#%22Value-types%22) in the docs:

```julia
struct Order{N} end
Order(N) = Order{N}()

fc_order(::Order{i}) where {i} = SVector(vcat(
    zeros(SVector{i}),
    vcat(1, zeros(SVector{9-i}))
))

```

This, however, only works if in `fc_order(Order(n))`, `n` is known at compilation. When used in a loop in a function, it also provoked type instability (below, x is of type `Any`):

```julia
julia> function loop_fc(::Order{n}) where n
           for i in 1:n
               x = fc_order(Order(i))
           end
       end
loop_fc (generic function with 1 method)

julia> @code_warntype loop_fc(Order(3))
MethodInstance for loop_fc(::Order{3})
  from loop_fc(::Order{n}) where n @ Main REPL[65]:1
Static Parameters
  n = 3
Arguments
  #self#::Core.Const(loop_fc)
  _::Core.Const(Order{3}())
Locals
  @_3::Union{Nothing, Tuple{Int64, Int64}}
  i::Int64
  x::Any
Body::Nothing
1 ─ %1 = (1:$(Expr(:static_parameter, 1)))::Core.Const(1:3)
│ (@_3 = Base.iterate(%1))
│ %3 = (@_3::Core.Const((1, 1)) === nothing)::Core.Const(false)
│ %4 = Base.not_int(%3)::Core.Const(true)
└── goto #4 if not %4
2 ┄ %6 = @_3::Tuple{Int64, Int64}
│ (i = Core.getfield(%6, 1))
│ %8 = Core.getfield(%6, 2)::Int64
│ %9 = Main.Order(i)::Order
│ (x = Main.fc_order(%9))
│ (@_3 = Base.iterate(%1, %8))
│ %12 = (@_3 === nothing)::Bool
│ %13 = Base.not_int(%12)::Bool
└── goto #4 if not %13
3 ─ goto #2
4 ┄ return nothing

```

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [June 27, 2024, 8:32am UTC](https://discourse.julialang.org/t/create-svector-with-one-non-zero-value/116295/2 "2024-06-27T08:32:52Z")

</div>

You can probably use the function `ntuple`

---

<div class="post-metadata">

**Author:** ![Alseidon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alseidon/32/207775_2.png) [@Alseidon](https://discourse.julialang.org/u/Alseidon)\
**Post date:** [June 27, 2024, 8:41am UTC](https://discourse.julialang.org/t/create-svector-with-one-non-zero-value/116295/3 "2024-06-27T08:41:52Z")

</div>

It worked, many thanks!

For the record, the correct function is:

```julia
# Type stable, no allocation
fc_tuple(i) = SVector( ntuple( x->x == i ? 1 : 0, Val(10) ) )

# With size as parameter
fc(i, ::Order{ord}) where {ord} = SVector(
    ntuple(x->x == i ? 1 : 0, Val(ord))
)

```

EDIT: attention! `ntuple(f, n)` forgets the size information if `n > 10`. You have to write `ntuple(f, Val(n))` to keep the size information. I edited the functions accordingly.

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [June 27, 2024, 8:52am UTC](https://discourse.julialang.org/t/create-svector-with-one-non-zero-value/116295/4 "2024-06-27T08:52:54Z")

</div>

You can also try FillArrays.jl `OneElement` type, which does exactly what your `fc(i, ::ord)` function does:

```julia
using FilArrays
OneElement(i,order) # Vector of lenght order, where everything is zero except for index i, which is 1

```

That might be beneficial since it also knows about the sparse structure and won’t try to multiply the zero elements with something else 🙂

> **[Home · FillArrays.jl](https://juliaarrays.github.io/FillArrays.jl/stable/#FillArrays.OneElement-Tuple%7BInt64,%20Int64%7D)**
>
> Documentation for FillArrays.jl.

---

<div class="post-metadata">

**Author:** ![Alseidon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alseidon/32/207775_2.png) [@Alseidon](https://discourse.julialang.org/u/Alseidon)\
**Post date:** [June 27, 2024, 9:28am UTC](https://discourse.julialang.org/t/create-svector-with-one-non-zero-value/116295/5 "2024-06-27T09:28:01Z")

</div>

Actually, it wouldn’t work in my case because I need the `SVector` type, but I will keep that in mind for other applications!

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [June 27, 2024, 10:04am UTC](https://discourse.julialang.org/t/create-svector-with-one-non-zero-value/116295/6 "2024-06-27T10:04:02Z")

</div>

You may convert a `OneElement` to a `SVector`:

```julia
julia> using FillArrays, StaticArrays

julia> f(i) = SVector{3}(OneElement(i, 3))
f (generic function with 1 method)

julia> f(2)
3-element SVector{3, Int64} with indices SOneTo(3):
 0
 1
 0

julia> @btime f($(Ref(2))[])
  2.954 ns (0 allocations: 0 bytes)
3-element SVector{3, Int64} with indices SOneTo(3):
 0
 1
 0

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [June 27, 2024, 10:51am UTC](https://discourse.julialang.org/t/create-svector-with-one-non-zero-value/116295/7 "2024-06-27T10:51:48Z")

</div>

I believe the canonical solution is to use `StaticArrays.setindex` (without `!`), like this:

```julia
fc(i::Int) = setindex(zeros(SVector{10, Float64}), 1, i)

```

No other libraries necessary.

If you want the size to be configurable, use the regular `Val` provided by Base instead of a custom `Order`:

```julia
fc(::Val{N}, i::Int) where {N} = setindex(zeros(SVector{N, Float64}), 1, i)

```

Example:

```julia
julia> fc(Val(5), 2)
5-element SVector{5, Float64} with indices SOneTo(5):
 0.0
 1.0
 0.0
 0.0
 0.0

```

---

<div class="post-metadata">

**Author:** ![Alseidon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alseidon/32/207775_2.png) [@Alseidon](https://discourse.julialang.org/u/Alseidon)\
**Post date:** [June 27, 2024, 11:25am UTC](https://discourse.julialang.org/t/create-svector-with-one-non-zero-value/116295/8 "2024-06-27T11:25:40Z")

</div>

This seems like “cleaner” Julia code indeed.

I used `Order` instead of `Val` in my original code to make the code more readable; I will just write `Order = Val` to keep it this way.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [June 27, 2024, 11:29am UTC](https://discourse.julialang.org/t/create-svector-with-one-non-zero-value/116295/9 "2024-06-27T11:29:56Z")

</div>

You can do that, but `Val` is the standard way, and is easily recognizable for other users. So personally, I would stick with `Val`.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [June 27, 2024, 11:51am UTC](https://discourse.julialang.org/t/create-svector-with-one-non-zero-value/116295/10 "2024-06-27T11:51:24Z")

</div>

> [@Alseidon](#):
>
> I will just write `Order = Val` to keep it this way.

Oh, BTW, if you absolutely prefer using `Order`, you should write

```julia
const Order = Val

```

to make the binding constant, otherwise you may experience performance issues.

---

<div class="post-metadata">

**Author:** ![Alseidon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alseidon/32/207775_2.png) [@Alseidon](https://discourse.julialang.org/u/Alseidon)\
**Post date:** [June 27, 2024, 12:01pm UTC](https://discourse.julialang.org/t/create-svector-with-one-non-zero-value/116295/11 "2024-06-27T12:01:15Z")

</div>

Thank you for the answer!! I will think about what’s best for my use case.

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [June 27, 2024, 2:03pm UTC](https://discourse.julialang.org/t/create-svector-with-one-non-zero-value/116295/12 "2024-06-27T14:03:16Z")

</div>

If it suits you, defining your own `StaticArrays` type is [dead simple](https://juliaarrays.github.io/StaticArrays.jl/stable/pages/api/#Implementing-your-own-types):

```julia
using StaticArrays

struct OneHotSVector{N,T} <: StaticVector{N,T}
	val::T
	ind::Int
end

OneHotSVector{N}(val::T, ind) where {N,T} = OneHotSVector{N,T}(val, ind) # autodetect the eltype

Base.@propagate_inbounds function Base.getindex(v::OneHotSVector, i::Int)
	@boundscheck checkbounds(v, i)
	return i==v.ind ? v.val : zero(v.val)
end

```

```julia-repl
julia> OneHotSVector{3}(1.0, 2) * OneHotSVector{2}(1.0, 1)'
3×2 SMatrix{3, 2, Float64, 6} with indices SOneTo(3)×SOneTo(2):
 0.0 0.0
 1.0 0.0
 0.0 0.0

```
