Vectorized variable assignment (assign matrix off diagonal values)

Hello world,

I would like to make a matrix with some value A0 down the main diagonal, and some value A1 along the sub/superdiagonal (as defined https://en.wikipedia.org/wiki/Diagonal#Matrices). Is there a way to assign a value to all entries at indices like (i, i+1) or (i, i-1) without an external for loop like:

for i in 1:n
	out[i, i] = A0
	out[i, 1 + i % n] = A1
	out[1 + i % n, i] = A1
end

?

The function setindex! seems to only support assigning value to a square region of your matrix, which isn’t sufficiently general. I also tried playing with LinearIndices, but that seems to be using auxiliary memory proportional to the size of the matrix, which seems silly.

So, what is the best way of assigning some arbitrary set of indices in a matrix one or more values? I suppose there are two cases worth considering: one where I want to set a series of matrix elements to some constant value, and one where we set each element to a corresponding member of another list.

Since Julia boasts such efficiency for numerical/vector ops, I’m hoping there is a syntactically clean way to do this without much memory overhead.

Thanks!
Alex

You can use diagind from LinearAlgebra:

julia> using LinearAlgebra

julia> out = zeros(5, 5)
5×5 Array{Float64,2}:
 0.0  0.0  0.0  0.0  0.0
 0.0  0.0  0.0  0.0  0.0
 0.0  0.0  0.0  0.0  0.0
 0.0  0.0  0.0  0.0  0.0
 0.0  0.0  0.0  0.0  0.0

julia> out[diagind(out, 0)] .= 1
       out[diagind(out, -1)] .= 2
       out[diagind(out, 1)] .= 3
       out
5×5 Array{Float64,2}:
 1.0  3.0  0.0  0.0  0.0
 2.0  1.0  3.0  0.0  0.0
 0.0  2.0  1.0  3.0  0.0
 0.0  0.0  2.0  1.0  3.0
 0.0  0.0  0.0  2.0  1.0
3 Likes

Since you mention memory overhead, have you had a look at BandedMatrices.jl ?

2 Likes

You can use the built-in SymTridiagonal type, which uses minimal memory and has fast algorithms for things like A \ b.

using LinearAlgebra
A = SymTridiagonal(rmul!(ones(n),A0), rmul!(ones(n-1),A1))

Note, however, that there is nothing wrong with using a for loop in a pinch. Loops in Julia are fast, just as fast as the “vectorized” operations.

Thank you three for your responses - those thoroughly solve the problem of off diagonal matrix elements!