Skip to content

Commit 2a2b93c

Browse files
committed
Make fillband! public and specialize for banded matrices
1 parent 3537c3a commit 2a2b93c

File tree

12 files changed

+357
-1
lines changed

12 files changed

+357
-1
lines changed

src/LinearAlgebra.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ public AbstractTriangular,
180180
symmetric_type,
181181
zeroslike,
182182
matprod_dest,
183-
fillstored!
183+
fillstored!,
184+
fillband!
184185

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

src/bidiag.jl

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,3 +1543,30 @@ function Base._sum(A::Bidiagonal, dims::Integer)
15431543
end
15441544
res
15451545
end
1546+
1547+
function fillband!(B::Bidiagonal, x, l, u)
1548+
if l > u
1549+
return B
1550+
end
1551+
if ((B.uplo == 'U' && (l < 0 || u > 1)) ||
1552+
(B.uplo == 'L' && (l < -1 || u > 0))) && !iszero(x)
1553+
throw_fillband_error(l, u, x)
1554+
else
1555+
if B.uplo == 'U'
1556+
if l <= 1 <= u
1557+
fill!(B.ev, x)
1558+
end
1559+
if l <= 0 <= u
1560+
fill!(B.dv, x)
1561+
end
1562+
else # B.uplo == 'L'
1563+
if l <= 0 <= u
1564+
fill!(B.dv, x)
1565+
end
1566+
if l <= -1 <= u
1567+
fill!(B.ev, x)
1568+
end
1569+
end
1570+
end
1571+
return B
1572+
end

src/dense.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,23 @@ tril(M::Matrix, k::Integer) = tril!(copy(M), k)
205205
fillband!(A::AbstractMatrix, x, l, u)
206206
207207
Fill the band between diagonals `l` and `u` with the value `x`.
208+
209+
# Examples
210+
```jldoctest
211+
julia> A = zeros(4,4)
212+
4×4 Matrix{Float64}:
213+
0.0 0.0 0.0 0.0
214+
0.0 0.0 0.0 0.0
215+
0.0 0.0 0.0 0.0
216+
0.0 0.0 0.0 0.0
217+
218+
julia> LinearAlgebra.fillband!(A, 2, 0, 1)
219+
4×4 Matrix{Float64}:
220+
2.0 2.0 0.0 0.0
221+
0.0 2.0 2.0 0.0
222+
0.0 0.0 2.0 2.0
223+
0.0 0.0 0.0 2.0
224+
```
208225
"""
209226
function fillband!(A::AbstractMatrix{T}, x, l, u) where T
210227
require_one_based_indexing(A)

src/diagonal.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,3 +1216,18 @@ end
12161216

12171217
uppertriangular(D::Diagonal) = D
12181218
lowertriangular(D::Diagonal) = D
1219+
1220+
throw_fillband_error(l, u, x) = throw(ArgumentError(lazy"cannot set bands $l:$u to a nonzero value ($x)"))
1221+
1222+
function fillband!(D::Diagonal, x, l, u)
1223+
if l > u
1224+
return D
1225+
end
1226+
if (l < 0 || u > 0) && !iszero(x)
1227+
throw_fillband_error(l, u, x)
1228+
end
1229+
if l <= 0 <= u
1230+
fill!(D.diag, x)
1231+
end
1232+
return D
1233+
end

src/hessenberg.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,17 @@ lmul!(x::Number, H::UpperHessenberg) = (lmul!(x, H.data); H)
124124

125125
fillstored!(H::UpperHessenberg, x) = (fillband!(H.data, x, -1, size(H,2)-1); H)
126126

127+
function fillband!(H::UpperHessenberg, x, l, u)
128+
if l > u
129+
return H
130+
end
131+
if l < -1 && !iszero(x)
132+
throw_fillband_error(l, u, x)
133+
end
134+
fillband!(H.data, x, l, u)
135+
return H
136+
end
137+
127138
+(A::UpperHessenberg, B::UpperHessenberg) = UpperHessenberg(A.data+B.data)
128139
-(A::UpperHessenberg, B::UpperHessenberg) = UpperHessenberg(A.data-B.data)
129140

src/triangular.jl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,36 @@ fillstored!(A::UnitLowerTriangular, x) = (fillband!(A.data, x, 1-size(A,1), -1);
931931
fillstored!(A::UpperTriangular, x) = (fillband!(A.data, x, 0, size(A,2)-1); A)
932932
fillstored!(A::UnitUpperTriangular, x) = (fillband!(A.data, x, 1, size(A,2)-1); A)
933933

934+
function fillband!(A::LowerOrUnitLowerTriangular, x, l, u)
935+
if l > u
936+
return A
937+
end
938+
if u > 0 && !iszero(x)
939+
throw_fillband_error(l, u, x)
940+
end
941+
isunit = A isa UnitLowerTriangular
942+
if isunit && u >= 0 && x != oneunit(x)
943+
throw(ArgumentError(lazy"cannot set the diagonal band to a non-unit value ($x)"))
944+
end
945+
fillband!(A.data, x, l, min(u, -isunit))
946+
return A
947+
end
948+
949+
function fillband!(A::UpperOrUnitUpperTriangular, x, l, u)
950+
if l > u
951+
return A
952+
end
953+
if l < 0 && !iszero(x)
954+
throw_fillband_error(l, u, x)
955+
end
956+
isunit = A isa UnitUpperTriangular
957+
if isunit && l <= 0 && x != oneunit(x)
958+
throw(ArgumentError(lazy"cannot set the diagonal band to a non-unit value ($x)"))
959+
end
960+
fillband!(A.data, x, max(l, isunit), u)
961+
return A
962+
end
963+
934964
# Binary operations
935965
# use broadcasting if the parents are strided, where we loop only over the triangular part
936966
function +(A::UpperTriangular, B::UpperTriangular)

src/tridiag.jl

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,3 +1189,44 @@ function _opnorm1Inf(A::SymTridiagonal, p::Real)
11891189
),
11901190
normfirst, normend)
11911191
end
1192+
1193+
function fillband!(T::Tridiagonal, x, l, u)
1194+
if l > u
1195+
return T
1196+
end
1197+
if (l < -1 || u > 1) && !iszero(x)
1198+
throw_fillband_error(l, u, x)
1199+
else
1200+
if l <= -1 <= u
1201+
fill!(T.dl, x)
1202+
end
1203+
if l <= 0 <= u
1204+
fill!(T.d, x)
1205+
end
1206+
if l <= 1 <= u
1207+
fill!(T.du, x)
1208+
end
1209+
end
1210+
return T
1211+
end
1212+
1213+
function fillband!(T::SymTridiagonal, x, l, u)
1214+
if l > u
1215+
return T
1216+
end
1217+
if (l <= 1 <= u) != (l <= -1 <= u)
1218+
throw(ArgumentError(lazy"cannot set only one off-diagonal band of a SymTridiagonal"))
1219+
elseif (l < -1 || u > 1) && !iszero(x)
1220+
throw_fillband_error(l, u, x)
1221+
elseif l <= 0 <= u && !issymmetric(x)
1222+
throw(ArgumentError(lazy"cannot set entries in the diagonal band of a SymTridiagonal to an asymmetric value $x"))
1223+
else
1224+
if l <= 0 <= u
1225+
fill!(T.dv, x)
1226+
end
1227+
if l <= 1 <= u
1228+
fill!(T.ev, x)
1229+
end
1230+
end
1231+
return T
1232+
end

test/bidiag.jl

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,4 +1246,56 @@ end
12461246
end
12471247
end
12481248

1249+
@testset "fillband!" begin
1250+
@testset "uplo = :U" begin
1251+
B = Bidiagonal(zeros(4), zeros(3), :U)
1252+
LinearAlgebra.fillband!(B, 2, 1, 1)
1253+
@test all(==(2), diagview(B,1))
1254+
LinearAlgebra.fillband!(B, 3, 0, 0)
1255+
@test all(==(3), diagview(B,0))
1256+
@test all(==(2), diagview(B,1))
1257+
LinearAlgebra.fillband!(B, 4, 0, 1)
1258+
@test all(==(4), diagview(B,0))
1259+
@test all(==(4), diagview(B,1))
1260+
@test_throws ArgumentError LinearAlgebra.fillband!(B, 3, -1, 0)
1261+
1262+
LinearAlgebra.fillstored!(B, 1)
1263+
LinearAlgebra.fillband!(B, 0, -3, 3)
1264+
@test iszero(B)
1265+
LinearAlgebra.fillband!(B, 0, -10, 10)
1266+
@test iszero(B)
1267+
LinearAlgebra.fillstored!(B, 1)
1268+
B2 = copy(B)
1269+
LinearAlgebra.fillband!(B, 0, -1, -3)
1270+
@test B == B2
1271+
LinearAlgebra.fillband!(B, 0, 10, 10)
1272+
@test B == B2
1273+
end
1274+
1275+
@testset "uplo = :L" begin
1276+
B = Bidiagonal(zeros(4), zeros(3), :L)
1277+
LinearAlgebra.fillband!(B, 2, -1, -1)
1278+
@test all(==(2), diagview(B,-1))
1279+
LinearAlgebra.fillband!(B, 3, 0, 0)
1280+
@test all(==(3), diagview(B,0))
1281+
@test all(==(2), diagview(B,-1))
1282+
LinearAlgebra.fillband!(B, 4, -1, 0)
1283+
@test all(==(4), diagview(B,0))
1284+
@test all(==(4), diagview(B,-1))
1285+
@test_throws ArgumentError LinearAlgebra.fillband!(B, 3, 0, 1)
1286+
1287+
LinearAlgebra.fillstored!(B, 1)
1288+
LinearAlgebra.fillband!(B, 0, -3, 3)
1289+
@test iszero(B)
1290+
LinearAlgebra.fillband!(B, 0, -10, 10)
1291+
@test iszero(B)
1292+
LinearAlgebra.fillstored!(B, 1)
1293+
B2 = copy(B)
1294+
LinearAlgebra.fillband!(B, 0, -1, -3)
1295+
@test B == B2
1296+
LinearAlgebra.fillband!(B, 0, 10, 10)
1297+
@test B == B2
1298+
end
1299+
end
1300+
12491301
end # module TestBidiagonal

test/diagonal.jl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1542,4 +1542,26 @@ end
15421542
end
15431543
end
15441544

1545+
@testset "fillband!" begin
1546+
D = Diagonal(zeros(4))
1547+
LinearAlgebra.fillband!(D, 2, 0, 0)
1548+
@test all(==(2), diagview(D,0))
1549+
@test all(==(0), diagview(D,-1))
1550+
@test_throws ArgumentError LinearAlgebra.fillband!(D, 3, -2, 2)
1551+
1552+
LinearAlgebra.fillstored!(D, 1)
1553+
LinearAlgebra.fillband!(D, 0, -3, 3)
1554+
@test iszero(D)
1555+
LinearAlgebra.fillstored!(D, 1)
1556+
LinearAlgebra.fillband!(D, 0, -10, 10)
1557+
@test iszero(D)
1558+
1559+
LinearAlgebra.fillstored!(D, 1)
1560+
D2 = copy(D)
1561+
LinearAlgebra.fillband!(D, 0, -1, -3)
1562+
@test D == D2
1563+
LinearAlgebra.fillband!(D, 0, 10, 10)
1564+
@test D == D2
1565+
end
1566+
15451567
end # module TestDiagonal

test/hessenberg.jl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,4 +300,24 @@ end
300300
@test_throws DimensionMismatch hessenberg(zeros(0,0)).Q * ones(1, 2)
301301
end
302302

303+
@testset "fillband" begin
304+
U = UpperHessenberg(zeros(4,4))
305+
@test_throws ArgumentError LinearAlgebra.fillband!(U, 1, -2, 1)
306+
@test iszero(U)
307+
308+
LinearAlgebra.fillband!(U, 10, -1, 2)
309+
@test all(==(10), diagview(U,-1))
310+
@test all(==(10), diagview(U,2))
311+
@test all(==(0), diagview(U,3))
312+
313+
LinearAlgebra.fillband!(U, 0, -5, 5)
314+
@test iszero(U)
315+
316+
U2 = copy(U)
317+
LinearAlgebra.fillband!(U, -10, 1, -2)
318+
@test U == U2
319+
LinearAlgebra.fillband!(U, -10, 10, 10)
320+
@test U == U2
321+
end
322+
303323
end # module TestHessenberg

0 commit comments

Comments
 (0)