# Change the diagonal of an AbstractMatrix in place

To add an AbstractVector `v` to the diagonal of an AbstractMatrix `M`, one can do

``````using LinearAlgebra
M + Diagonal(v)
``````

Is there a way to do the same thing without creating a new matrix (i.e., modify `M` in place)? I’m looking for a one-liner that would be as fast and work for Matrix, DiagonalMatrix, TridiagonalMatrix etc…

I’ve tried using broadcasting but it is not as fast as it could be:

``````using LinearAlgebra, BenchmarkTools
N = 10_000
M = Tridiagonal(ones(N-1), ones(N), ones(N-1))
v = ones(N)
@btime M + Diagonal(v)
# 13.545 μs (8 allocations: 234.58 KiB)
@btime M .= M .+ Diagonal(v)
# 67.193 μs (3 allocations: 80 bytes)
``````

Not too general (relying on an implementation detail) but fast:

``````julia> @btime \$M.d .= \$v;
2.449 μs (0 allocations: 0 bytes)

julia> @btime \$M + Diagonal(\$v); # for comparison on my machine
19.084 μs (7 allocations: 234.56 KiB)

julia> @btime \$M .= \$M .+ Diagonal(\$v); # for comparison on my machine
104.632 μs (0 allocations: 0 bytes)
``````
1 Like

The obvious and general (but slower) answer is `@view(M[diagind(M)]) .= v`

``````julia> @btime @view(\$M[diagind(\$M)]) .= \$v;
86.377 μs (0 allocations: 0 bytes)
``````

And, just for the fun of it, the basic loop implementation:

``````julia> function f!(M,v)
@assert size(M, 1) == size(M, 2)
@assert length(v) == size(M, 1)
for i in axes(M, 1)
@inbounds M[i,i] = v[i]
end
return M
end
f! (generic function with 1 method)

julia> @btime f!(\$M,\$v);
77.950 μs (0 allocations: 0 bytes)
``````