Skip to content

Commit bdae975

Browse files
committed
rewrite fillstored!(::SpecialMatrix, x) without generated function
move implementations to more suitable places
1 parent 8148227 commit bdae975

File tree

4 files changed

+67
-83
lines changed

4 files changed

+67
-83
lines changed

base/linalg/bidiag.jl

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -601,37 +601,3 @@ function eigvecs(M::Bidiagonal{T}) where T
601601
Q #Actually Triangular
602602
end
603603
eigfact(M::Bidiagonal) = Eigen(eigvals(M), eigvecs(M))
604-
605-
# fill! methods
606-
_valuefields(::Type{<:Diagonal}) = [:diag]
607-
_valuefields(::Type{<:Bidiagonal}) = [:dv, :ev]
608-
_valuefields(::Type{<:Tridiagonal}) = [:dl, :d, :du]
609-
_valuefields(::Type{<:SymTridiagonal}) = [:dv, :ev]
610-
_valuefields(::Type{<:AbstractTriangular}) = [:data]
611-
612-
const SpecialArrays = Union{Diagonal,Bidiagonal,Tridiagonal,SymTridiagonal,AbstractTriangular}
613-
614-
function fillstored!(A::SpecialArrays, x)
615-
xT = convert(eltype(A), x)
616-
if @generated
617-
quote
618-
$([ :(fill!(A.$field, xT)) for field in _valuefields(A) ]...)
619-
end
620-
else
621-
for field in _valuefields(A)
622-
fill!(getfield(A, field), xT)
623-
end
624-
end
625-
return A
626-
end
627-
628-
_small_enough(A::Bidiagonal) = size(A, 1) <= 1
629-
_small_enough(A::Tridiagonal) = size(A, 1) <= 2
630-
_small_enough(A::SymTridiagonal) = size(A, 1) <= 2
631-
632-
function fill!(A::Union{Bidiagonal,Tridiagonal,SymTridiagonal}, x)
633-
xT = convert(eltype(A), x)
634-
(xT == zero(eltype(A)) || _small_enough(A)) && return fillstored!(A, xT)
635-
throw(ArgumentError("array A of type $(typeof(A)) and size $(size(A)) can
636-
not be filled with x=$x, since some of its entries are constrained."))
637-
end

base/linalg/special.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,21 @@ end
124124

125125
A_mul_Bc!(A::AbstractTriangular, B::Union{QRCompactWYQ,QRPackedQ}) = A_mul_Bc!(full!(A), B)
126126
A_mul_Bc(A::AbstractTriangular, B::Union{QRCompactWYQ,QRPackedQ}) = A_mul_Bc(copy!(similar(parent(A)), A), B)
127+
128+
# fill[stored]! methods
129+
fillstored!(A::Diagonal, x) = (fill!(A.diag, x); A)
130+
fillstored!(A::Bidiagonal, x) = (fill!(A.dv, x); fill!(A.ev, x); A)
131+
fillstored!(A::Tridiagonal, x) = (fill!(A.dl, x); fill!(A.d, x); fill!(A.du, x); A)
132+
fillstored!(A::SymTridiagonal, x) = (fill!(A.dv, x); fill!(A.ev, x); A)
133+
134+
_small_enough(A::Bidiagonal) = size(A, 1) <= 1
135+
_small_enough(A::Tridiagonal) = size(A, 1) <= 2
136+
_small_enough(A::SymTridiagonal) = size(A, 1) <= 2
137+
138+
# TODO: Add Diagonal to this method when 0.7 deprecations are removed
139+
function fill!(A::Union{Bidiagonal,Tridiagonal,SymTridiagonal}, x)
140+
xT = convert(eltype(A), x)
141+
(iszero(xT) || _small_enough(A)) && return fillstored!(A, xT)
142+
throw(ArgumentError("array of type $(typeof(A)) and size $(size(A)) can
143+
not be filled with x=$x, since some of its entries are constrained."))
144+
end

base/linalg/triangular.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,8 @@ end
418418
scale!(A::Union{UpperTriangular,LowerTriangular}, c::Number) = scale!(A,A,c)
419419
scale!(c::Number, A::Union{UpperTriangular,LowerTriangular}) = scale!(A,c)
420420

421+
fillstored!(A::AbstractTriangular, x) = (fill!(A.data, x); A)
422+
421423
# Binary operations
422424
+(A::UpperTriangular, B::UpperTriangular) = UpperTriangular(A.data + B.data)
423425
+(A::LowerTriangular, B::LowerTriangular) = LowerTriangular(A.data + B.data)

test/linalg/bidiag.jl

Lines changed: 47 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -309,58 +309,56 @@ end
309309
@test promote(C,A) isa Tuple{Tridiagonal, Tridiagonal}
310310
end
311311

312-
import Base.LinAlg: fillstored!, UnitLowerTriangular
312+
using Base.LinAlg: fillstored!, UnitLowerTriangular
313313
@testset "fill! and fillstored!" begin
314-
let #fill!
315-
let # fillstored!
316-
A = Tridiagonal(randn(2), randn(3), randn(2))
317-
@test fillstored!(A, 3) == Tridiagonal([3, 3.], [3, 3, 3.], [3, 3.])
318-
B = Bidiagonal(randn(3), randn(2), :U)
319-
@test fillstored!(B, 2) == Bidiagonal([2.,2,2], [2,2.], :U)
320-
S = SymTridiagonal(randn(3), randn(2))
321-
@test fillstored!(S, 1) == SymTridiagonal([1,1,1.], [1,1.])
322-
Ult = UnitLowerTriangular(randn(3,3))
323-
@test fillstored!(Ult, 3) == UnitLowerTriangular([1 0 0; 3 1 0; 3 3 1])
324-
end
325-
let # fill!(exotic, 0)
326-
exotic_arrays = Any[Tridiagonal(randn(3), randn(4), randn(3)),
327-
Bidiagonal(randn(3), randn(2), rand([:U,:L])),
328-
SymTridiagonal(randn(3), randn(2)),
329-
sparse(randn(3,4)),
330-
# Diagonal(randn(5)), # Diagonal fill! deprecated, see below
331-
sparse(rand(3)),
332-
# LowerTriangular(randn(3,3)), # AbstractTriangular fill! deprecated, see below
333-
# UpperTriangular(randn(3,3)) # AbstractTriangular fill! deprecated, see below
334-
]
335-
for A in exotic_arrays
336-
fill!(A, 0)
337-
for a in A
338-
@test a == 0
339-
end
314+
let # fillstored!
315+
A = Tridiagonal(randn(2), randn(3), randn(2))
316+
@test fillstored!(A, 3) == Tridiagonal([3, 3.], [3, 3, 3.], [3, 3.])
317+
B = Bidiagonal(randn(3), randn(2), :U)
318+
@test fillstored!(B, 2) == Bidiagonal([2.,2,2], [2,2.], :U)
319+
S = SymTridiagonal(randn(3), randn(2))
320+
@test fillstored!(S, 1) == SymTridiagonal([1,1,1.], [1,1.])
321+
Ult = UnitLowerTriangular(randn(3,3))
322+
@test fillstored!(Ult, 3) == UnitLowerTriangular([1 0 0; 3 1 0; 3 3 1])
323+
end
324+
let # fill!(exotic, 0)
325+
exotic_arrays = Any[Tridiagonal(randn(3), randn(4), randn(3)),
326+
Bidiagonal(randn(3), randn(2), rand([:U,:L])),
327+
SymTridiagonal(randn(3), randn(2)),
328+
sparse(randn(3,4)),
329+
# Diagonal(randn(5)), # Diagonal fill! deprecated, see below
330+
sparse(rand(3)),
331+
# LowerTriangular(randn(3,3)), # AbstractTriangular fill! deprecated, see below
332+
# UpperTriangular(randn(3,3)) # AbstractTriangular fill! deprecated, see below
333+
]
334+
for A in exotic_arrays
335+
fill!(A, 0)
336+
for a in A
337+
@test a == 0
340338
end
341-
# Diagonal and AbstractTriangular fill! were defined as fillstored!,
342-
# not matching the general behavior of fill!, and so have been deprecated.
343-
# In a future dev cycle, these fill! methods should probably be reintroduced
344-
# with behavior matching that of fill! for other structured matrix types.
345-
# In the interm, equivalently test fillstored! below
346-
@test iszero(fillstored!(Diagonal(fill(1, 3)), 0))
347-
@test iszero(fillstored!(LowerTriangular(fill(1, 3, 3)), 0))
348-
@test iszero(fillstored!(UpperTriangular(fill(1, 3, 3)), 0))
349339
end
350-
let # fill!(small, x)
351-
val = randn()
352-
b = Bidiagonal(randn(1,1), :U)
353-
st = SymTridiagonal(randn(1,1))
354-
for x in (b, st)
355-
@test Array(fill!(x, val)) == fill!(Array(x), val)
356-
end
357-
b = Bidiagonal(randn(2,2), :U)
358-
st = SymTridiagonal(randn(3), randn(2))
359-
t = Tridiagonal(randn(3,3))
360-
for x in (b, t, st)
361-
@test_throws ArgumentError fill!(x, val)
362-
@test Array(fill!(x, 0)) == fill!(Array(x), 0)
363-
end
340+
# Diagonal and AbstractTriangular fill! were defined as fillstored!,
341+
# not matching the general behavior of fill!, and so have been deprecated.
342+
# In a future dev cycle, these fill! methods should probably be reintroduced
343+
# with behavior matching that of fill! for other structured matrix types.
344+
# In the interm, equivalently test fillstored! below
345+
@test iszero(fillstored!(Diagonal(fill(1, 3)), 0))
346+
@test iszero(fillstored!(LowerTriangular(fill(1, 3, 3)), 0))
347+
@test iszero(fillstored!(UpperTriangular(fill(1, 3, 3)), 0))
348+
end
349+
let # fill!(small, x)
350+
val = randn()
351+
b = Bidiagonal(randn(1,1), :U)
352+
st = SymTridiagonal(randn(1,1))
353+
for x in (b, st)
354+
@test Array(fill!(x, val)) == fill!(Array(x), val)
355+
end
356+
b = Bidiagonal(randn(2,2), :U)
357+
st = SymTridiagonal(randn(3), randn(2))
358+
t = Tridiagonal(randn(3,3))
359+
for x in (b, t, st)
360+
@test_throws ArgumentError fill!(x, val)
361+
@test Array(fill!(x, 0)) == fill!(Array(x), 0)
364362
end
365363
end
366364
end

0 commit comments

Comments
 (0)