# Linear Algebra - Unit vectors e_i

Hi,

Is there an easy way to add a standard unit vector (e_i, which is vector of length ‘l’ with all zeros except for ith position?
Example: Let `x` be a vector of length `5`. I want to add e_3 (= [ 0 0 1 0 0]) to it.
Right now I’m doing it as

``````y = x + eye(5)[:,3]
``````

Is there any nice way to do it like `x + e[3]` kind of syntax?

Regards,
vish

`x[3] += 1`?

1 Like

My actual use case is a little more complicated: I need to do

``````y = (1-c) * x + c * e_3
``````
``````y = (1-c) * x
y[3] += c
``````

maybe

Yeah… that’s one way. But it’s still two lines
But is there any way to do this in one line?
Or May be I should settle with this.

``````y = (1-c) * x; y[3] += c
``````

11 Likes

Possibly yes. There is a trade-off between brevity and transparency; introducing special syntax for all of these things in `Base` is probably not worth it. If, however, you do this a lot in a package, you could write a tiny function for it. Especially if you want to make it generic so that it can handle `StaticVector` and other special types.

It could maybe be useful to have a lazy array, like I (UniformScaling), defined by e(i)[j] = i == j ? 1 : 0. Then one could define I[:,i] to be equal to that, for instance. That could be a neat little package.

1 Like

`y = (1 - c) .* x .+ c .* (1:5 .== 3)`

6 Likes

I’ve often wanted this myself. Julia prides itself in being readable and close to Mathematical notation so I think this was a perfectly fair question.

1 Like

Yes, I think this would be an excellent addition to FillArrays, along with the sort of stuff I mentioned in Possibility of a generically sized vector of 1s and 0s similar to the UniformScalingOperator in Juila v0.7

A bold e (as an optional function name in those cases) is one possible syntactic sugar

1 Like

I think for the moment @yuyichao answer is the closest possible solution for this.
And @antoine-levitt also has some interesting stuff!

Another possible use case for a similar lazy array: the totally antisymmetric tensor (Levi-Civita symbol), with bonus points for implementing fast contractions with it.

1 Like
``````struct lazy_e{T} <: AbstractVector{T}
i::Int
n::Int
end
lazy_e(i::Int, n::Int, ::Type{T} = Int) where T = lazy_e{T}(i, n)
function Base.getindex(e::lazy_e{T}, i) where T
@boundscheck @assert i <= e.n
ifelse(i == e.i, one(T), zero(T))
end
Base.size(e::lazy_e) = (e.n,)
``````

Then on Julia 0.7:

``````julia> fe(x) = (@inbounds d = x' * lazy_e(3,4); d)
fe (generic function with 1 method)

julia> using StaticArrays, BenchmarkTools

julia> x = @SVector randn(4)
4-element SArray{Tuple{4},Float64,1,4}:
-0.02571662495110571
-0.2620502046882458
-0.8456889511406026
0.017055806672449558

julia> y = randn(4)
4-element Array{Float64,1}:
-1.858893446204762
1.883085443252701
-0.7957485906904918
-0.5190800039346426

julia> @btime fe(\$x)
1.520 ns (0 allocations: 0 bytes)
-0.8456889511406026

julia> @btime fe(\$y)
8.301 ns (0 allocations: 0 bytes)
-0.7957485906904918

julia> lazy_e(2,5)
5-element lazy_e{Int64}:
0
1
0
0
0

julia> lazy_e(2,5)'
0  1  0  0  0
``````

EDIT:
Ideally, you’d do this with a for loop and `@eval`, and perhaps some other helper macros, but:

``````Base.:*(A::Matrix, e::lazy_e) = A[:, e.i]

Base.:*(A::Adjoint{T,Matrix{T}}, e::lazy_e) where T = A[:, e.i]
Base.:*(A::Transpose{T,Matrix{T}}, e::lazy_e) where T = A[:, e.i]
Base.:*(A::Adjoint{T,Vector{T}}, e::lazy_e) where T = A[e.i]
Base.:*(A::Transpose{T,Vector{T}}, e::lazy_e) where T = A[e.i]

Base.:*(A::Adjoint{T,lazy_e}, e::Matrix{T}) where T = A[e.i, :]
Base.:*(A::Transpose{T,lazy_e}, e::Matrix{T}) where T = A[e.i, :]
Base.:*(A::Adjoint{T,lazy_e}, e::Vector{T}) where T = A[e.i]
Base.:*(A::Transpose{T,lazy_e}, e::Vector{T}) where T = A[e.i]
``````

I had to get really specific for dispatch to actually favor the newly defined multiplication methods, and I’m not sure why. This yielded:

``````julia> z = randn(3,4)
3×4 Array{Float64,2}:
0.478915  -0.542889  0.142261  -0.594415
0.509348   0.63491   1.77353   -0.545189
-0.659932   0.995295  1.706     -0.291947

julia> @btime \$z * lazy_e(2,4)
26.288 ns (1 allocation: 112 bytes)
3-element Array{Float64,1}:
-0.5428894820340465
0.6349099814045577
0.9952951252882498

julia> @btime \$z[:,2]
26.266 ns (1 allocation: 112 bytes)
3-element Array{Float64,1}:
-0.5428894820340465
0.6349099814045577
0.9952951252882498
``````

The matrix multiplication functions could be edited to return views if you.

3 Likes

@Elrod
I guess you rather want

``````struct lazy_e{T} <: AbstractVector{T}
i::Int
n::Int
val::T
end
``````

at least for `isbits(T)`, in order to quickly (without looping, independent of `n`) scale a unit vector and in-place add it to some other vector (specialize `broadcast!`).

1 Like
``````
unit(n)=eachcol(I(n))

unit(n,i)= unit(n)[i]
``````