# Change the diagonal of an AbstractMatrix in place

**URL:** https://discourse.julialang.org/t/change-the-diagonal-of-an-abstractmatrix-in-place/67294
**Category:** General Usage
**Tags:** linearalgebra, memory-allocation
**Created:** [August 29, 2021, 5:04pm UTC](https://discourse.julialang.org/t/change-the-diagonal-of-an-abstractmatrix-in-place/67294 "2021-08-29T17:04:29Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![matthieu](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@matthieu](https://discourse.julialang.org/u/matthieu)
#### Post date: [August 29, 2021, 5:04pm UTC](https://discourse.julialang.org/t/change-the-diagonal-of-an-abstractmatrix-in-place/67294/1 "2021-08-29T17:04:29Z")

</div>

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

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

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

```

---

<div class="post-metadata">

### Author: ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)
#### Post date: [August 29, 2021, 5:23pm UTC](https://discourse.julialang.org/t/change-the-diagonal-of-an-abstractmatrix-in-place/67294/2 "2021-08-29T17:23:08Z")

</div>

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

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

```

---

<div class="post-metadata">

### Author: ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)
#### Post date: [August 29, 2021, 5:30pm UTC](https://discourse.julialang.org/t/change-the-diagonal-of-an-abstractmatrix-in-place/67294/3 "2021-08-29T17:30:17Z")

</div>

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

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

```
