Skip to content

Commit f137858

Browse files
committed
Make fillstored! public (#1333)
`fillstored!` offers a way to fill only the stored indices of a structured matrix without having to populate the parent. E.g.: ```julia julia> U = UpperTriangular(zeros(4,4)) 4×4 UpperTriangular{Float64, Matrix{Float64}}: 0.0 0.0 0.0 0.0 ⋅ 0.0 0.0 0.0 ⋅ ⋅ 0.0 0.0 ⋅ ⋅ ⋅ 0.0 julia> LinearAlgebra.fillstored!(U, 2) 4×4 UpperTriangular{Float64, Matrix{Float64}}: 2.0 2.0 2.0 2.0 ⋅ 2.0 2.0 2.0 ⋅ ⋅ 2.0 2.0 ⋅ ⋅ ⋅ 2.0 ``` This seems like a useful function that should be public. This came up on discourse: https://discourse.julialang.org/t/how-to-set-all-elements-in-a-lower-triangular-matrix/128603
1 parent f6d16c2 commit f137858

File tree

5 files changed

+63
-8
lines changed

5 files changed

+63
-8
lines changed

src/LinearAlgebra.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,8 @@ public AbstractTriangular,
179179
symmetric,
180180
symmetric_type,
181181
zeroslike,
182-
matprod_dest
182+
matprod_dest,
183+
fillstored!
183184

184185
const BlasFloat = Union{Float64,Float32,ComplexF64,ComplexF32}
185186
const BlasReal = Union{Float64,Float32}

src/special.jl

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,10 +320,33 @@ _diag_or_value(A::Diagonal) = A.diag
320320
_diag_or_value(A::UniformScaling) = A.λ
321321

322322
# fill[stored]! methods
323+
"""
324+
fillstored!(A::AbstractMatrix, x)
325+
326+
Fill only the stored indices of a structured matrix `A` with the value `x`.
327+
328+
# Example
329+
```jldoctest
330+
julia> A = Tridiagonal(zeros(2), zeros(3), zeros(2))
331+
3×3 Tridiagonal{Float64, Vector{Float64}}:
332+
0.0 0.0 ⋅
333+
0.0 0.0 0.0
334+
⋅ 0.0 0.0
335+
336+
julia> LinearAlgebra.fillstored!(A, 2)
337+
3×3 Tridiagonal{Float64, Vector{Float64}}:
338+
2.0 2.0 ⋅
339+
2.0 2.0 2.0
340+
⋅ 2.0 2.0
341+
```
342+
"""
323343
fillstored!(A::Diagonal, x) = (fill!(A.diag, x); A)
324344
fillstored!(A::Bidiagonal, x) = (fill!(A.dv, x); fill!(A.ev, x); A)
325345
fillstored!(A::Tridiagonal, x) = (fill!(A.dl, x); fill!(A.d, x); fill!(A.du, x); A)
326-
fillstored!(A::SymTridiagonal, x) = (fill!(A.dv, x); fill!(A.ev, x); A)
346+
function fillstored!(A::SymTridiagonal, x)
347+
issymmetric(x) || throw(ArgumentError("cannot set a diagonal entry of a SymTridiagonal to an asymmetric value"))
348+
(fill!(A.dv, x); fill!(A.ev, x); A)
349+
end
327350

328351
_small_enough(A::Union{Diagonal, Bidiagonal}) = size(A, 1) <= 1
329352
_small_enough(A::Tridiagonal) = size(A, 1) <= 2

src/symmetric.jl

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -401,13 +401,11 @@ fill!(A::HermOrSym, x) = fillstored!(A, x)
401401
function fillstored!(A::HermOrSym{T}, x) where T
402402
xT = convert(T, x)
403403
if isa(A, Hermitian)
404-
isreal(xT) || throw(ArgumentError("cannot fill Hermitian matrix with a nonreal value"))
405-
end
406-
if A.uplo == 'U'
407-
fillband!(A.data, xT, 0, size(A,2)-1)
408-
else # A.uplo == 'L'
409-
fillband!(A.data, xT, 1-size(A,1), 0)
404+
ishermitian(xT) || throw(ArgumentError("cannot fill Hermitian matrix with a non-hermitian value"))
405+
elseif isa(A, Symmetric)
406+
issymmetric(xT) || throw(ArgumentError("cannot fill Symmetric matrix with an asymmetric value"))
410407
end
408+
applytri(A -> fillstored!(A, xT), A)
411409
return A
412410
end
413411

test/special.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,4 +835,28 @@ end
835835
end
836836
end
837837

838+
@testset "fillstored!" begin
839+
dv, ev = zeros(4), zeros(3)
840+
D = Diagonal(dv)
841+
LinearAlgebra.fillstored!(D, 2)
842+
@test D == diagm(fill(2, length(dv)))
843+
844+
dv .= 0
845+
B = Bidiagonal(dv, ev, :U)
846+
LinearAlgebra.fillstored!(B, 2)
847+
@test B == diagm(0=>fill(2, length(dv)), 1=>fill(2, length(ev)))
848+
849+
dv .= 0
850+
ev .= 0
851+
T = Tridiagonal(ev, dv, ev)
852+
LinearAlgebra.fillstored!(T, 2)
853+
@test T == diagm(-1=>fill(2, length(ev)), 0=>fill(2, length(dv)), 1=>fill(2, length(ev)))
854+
855+
dv .= 0
856+
ev .= 0
857+
ST = SymTridiagonal(dv, ev)
858+
LinearAlgebra.fillstored!(ST, 2)
859+
@test ST == diagm(-1=>fill(2, length(ev)), 0=>fill(2, length(dv)), 1=>fill(2, length(ev)))
860+
end
861+
838862
end # module TestSpecial

test/symmetric.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,4 +1165,13 @@ end
11651165
end
11661166
end
11671167

1168+
@testset "fillstored!" begin
1169+
A = zeros(4,4)
1170+
for T in (Symmetric, Hermitian)
1171+
A .= 0
1172+
LinearAlgebra.fillstored!(T(A), 2)
1173+
@test all(==(2), T(A))
1174+
end
1175+
end
1176+
11681177
end # module TestSymmetric

0 commit comments

Comments
 (0)