Skip to content

Commit 8ec2be0

Browse files
committed
improve copyto!(::AbstractMatrix,::SpecialMatrix)`
1 parent 8702ee7 commit 8ec2be0

File tree

5 files changed

+75
-41
lines changed

5 files changed

+75
-41
lines changed

stdlib/LinearAlgebra/src/bidiag.jl

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -165,29 +165,34 @@ function Base.replace_in_print_matrix(A::Bidiagonal,i::Integer,j::Integer,s::Abs
165165
end
166166

167167
#Converting from Bidiagonal to dense Matrix
168-
function Matrix{T}(A::Bidiagonal) where T
169-
n = size(A, 1)
170-
B = zeros(T, n, n)
171-
if n == 0
172-
return B
173-
end
174-
for i = 1:n - 1
175-
B[i,i] = A.dv[i]
176-
if A.uplo == 'U'
177-
B[i, i + 1] = A.ev[i]
178-
else
179-
B[i + 1, i] = A.ev[i]
180-
end
181-
end
182-
B[n,n] = A.dv[n]
183-
return B
184-
end
168+
Matrix{T}(A::Bidiagonal) where {T} = copyto!(Matrix{T}(undef, size(A)), A)
185169
Matrix(A::Bidiagonal{T}) where {T} = Matrix{T}(A)
186170
Array(A::Bidiagonal) = Matrix(A)
187171
promote_rule(::Type{Matrix{T}}, ::Type{<:Bidiagonal{S}}) where {T,S} =
188172
@isdefined(T) && @isdefined(S) ? Matrix{promote_type(T,S)} : Matrix
189173
promote_rule(::Type{Matrix}, ::Type{<:Bidiagonal}) = Matrix
190174

175+
function copyto!(A::AbstractMatrix{T}, B::Bidiagonal) where {T}
176+
require_one_based_indexing(A)
177+
n = size(B, 1)
178+
n == 0 && return A
179+
if size(A) == (n, n)
180+
fill!(A, zero(T))
181+
@inbounds for i in 1:n - 1
182+
A[i,i] = B.dv[i]
183+
if B.uplo == 'U'
184+
A[i, i + 1] = B.ev[i]
185+
else
186+
A[i + 1, i] = B.ev[i]
187+
end
188+
end
189+
A[n,n] = B.dv[n]
190+
return A
191+
else
192+
return @invoke copyto!(A::AbstractMatrix, B::AbstractMatrix)
193+
end
194+
end
195+
191196
#Converting from Bidiagonal to Tridiagonal
192197
function Tridiagonal{T}(A::Bidiagonal) where T
193198
dv = convert(AbstractVector{T}, A.dv)

stdlib/LinearAlgebra/src/diagonal.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,20 @@ similar(D::Diagonal, ::Type{T}) where {T} = Diagonal(similar(D.diag, T))
9191
similar(::Diagonal, ::Type{T}, dims::Union{Dims{1},Dims{2}}) where {T} = zeros(T, dims...)
9292

9393
copyto!(D1::Diagonal, D2::Diagonal) = (copyto!(D1.diag, D2.diag); D1)
94+
function copyto!(A::AbstractMatrix{T}, D::Diagonal) where {T}
95+
require_one_based_indexing(A)
96+
n = length(D.diag)
97+
n == 0 && return A
98+
if size(A) == (n, n)
99+
fill!(A, zero(T))
100+
@inbounds for i in 1:n
101+
A[i, i] = D.diag[i]
102+
end
103+
return A
104+
else
105+
return @invoke copyto!(A::AbstractMatrix, D::AbstractMatrix)
106+
end
107+
end
94108

95109
size(D::Diagonal) = (n = length(D.diag); (n,n))
96110

stdlib/LinearAlgebra/src/special.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,9 +300,9 @@ lmul!(Q::Adjoint{<:Any,<:QRPackedQ}, B::AbstractTriangular) = lmul!(Q, full!(B))
300300
function _qlmul(Q::AbstractQ, B)
301301
TQB = promote_type(eltype(Q), eltype(B))
302302
if size(Q.factors, 1) == size(B, 1)
303-
Bnew = Matrix{TQB}(B)
303+
Bnew = copy_similar(B, TQB)
304304
elseif size(Q.factors, 2) == size(B, 1)
305-
Bnew = [Matrix{TQB}(B); zeros(TQB, size(Q.factors, 1) - size(B,1), size(B, 2))]
305+
Bnew = [copy_similar(B, TQB); zeros(TQB, size(Q.factors, 1) - size(B,1), size(B, 2))]
306306
else
307307
throw(DimensionMismatch("first dimension of matrix must have size either $(size(Q.factors, 1)) or $(size(Q.factors, 2))"))
308308
end
@@ -331,9 +331,9 @@ function _qrmul(A, adjQ::Adjoint{<:Any,<:AbstractQ})
331331
Q = adjQ.parent
332332
TAQ = promote_type(eltype(A), eltype(Q))
333333
if size(A,2) == size(Q.factors, 1)
334-
Anew = Matrix{TAQ}(A)
334+
Anew = copy_similar(A, TAQ)
335335
elseif size(A,2) == size(Q.factors,2)
336-
Anew = [Matrix{TAQ}(A) zeros(TAQ, size(A, 1), size(Q.factors, 1) - size(Q.factors, 2))]
336+
Anew = [copy_similar(A, TAQ) zeros(TAQ, size(A, 1), size(Q.factors, 1) - size(Q.factors, 2))]
337337
else
338338
throw(DimensionMismatch("matrix A has dimensions $(size(A)) but matrix B has dimensions $(size(Q))"))
339339
end

stdlib/LinearAlgebra/src/tridiag.jl

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -122,17 +122,23 @@ SymTridiagonal(S::SymTridiagonal) = S
122122
AbstractMatrix{T}(S::SymTridiagonal) where {T} =
123123
SymTridiagonal(convert(AbstractVector{T}, S.dv)::AbstractVector{T},
124124
convert(AbstractVector{T}, S.ev)::AbstractVector{T})
125-
function Matrix{T}(M::SymTridiagonal) where T
125+
Matrix{T}(M::SymTridiagonal) where {T} = copyto!(Matrix{T}(undef, size(M)), M)
126+
function copyto!(A::AbstractMatrix{T}, M::SymTridiagonal) where {T}
127+
require_one_based_indexing(A)
126128
n = size(M, 1)
127-
Mf = zeros(T, n, n)
128-
n == 0 && return Mf
129-
@inbounds for i = 1:n-1
130-
Mf[i,i] = symmetric(M.dv[i], :U)
131-
Mf[i+1,i] = transpose(M.ev[i])
132-
Mf[i,i+1] = M.ev[i]
129+
n == 0 && return A
130+
if size(A) == (n, n)
131+
fill!(A, zero(T))
132+
@inbounds for i in 1:n-1
133+
A[i,i] = symmetric(M.dv[i], :U)
134+
A[i+1,i] = transpose(M.ev[i])
135+
A[i,i+1] = M.ev[i]
136+
end
137+
A[n,n] = symmetric(M.dv[n], :U)
138+
return A
139+
else
140+
return @invoke copyto!(A::AbstractMatrix, M::AbstractMatrix)
133141
end
134-
Mf[n,n] = symmetric(M.dv[n], :U)
135-
return Mf
136142
end
137143
Matrix(M::SymTridiagonal{T}) where {T} = Matrix{T}(M)
138144
Array(M::SymTridiagonal) = Matrix(M)
@@ -571,16 +577,24 @@ function size(M::Tridiagonal, d::Integer)
571577
end
572578
end
573579

574-
function Matrix{T}(M::Tridiagonal{T}) where T
575-
A = zeros(T, size(M))
576-
for i = 1:length(M.d)
577-
A[i,i] = M.d[i]
578-
end
579-
for i = 1:length(M.d)-1
580-
A[i+1,i] = M.dl[i]
581-
A[i,i+1] = M.du[i]
580+
Matrix{T}(M::Tridiagonal) where {T} = copyto!(Matrix{T}(undef, size(M)), M)
581+
582+
function copyto!(A::AbstractMatrix{T}, M::Tridiagonal) where {T}
583+
require_one_based_indexing(A)
584+
n = size(M, 1)
585+
n == 0 && return A
586+
if size(A) == (n, n)
587+
fill!(A, zero(T))
588+
@inbounds for i = 1:n-1
589+
A[i,i] = M.d[i]
590+
A[i+1,i] = M.dl[i]
591+
A[i,i+1] = M.du[i]
592+
end
593+
A[n,n] = M.d[n]
594+
return A
595+
else
596+
@invoke copyto!(A::AbstractMatrix, M::AbstractMatrix)
582597
end
583-
A
584598
end
585599
Matrix(M::Tridiagonal{T}) where {T} = Matrix{T}(M)
586600
Array(M::Tridiagonal) = Matrix(M)

stdlib/LinearAlgebra/test/special.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,12 +429,13 @@ end
429429
dl = [1, 1, 1]
430430
d = [1, 1, 1, 1]
431431
D = Diagonal(d)
432-
Bi = Bidiagonal(d, dl, :L)
432+
Bl = Bidiagonal(d, dl, :L)
433+
Bu = Bidiagonal(d, dl, :U)
433434
Tri = Tridiagonal(dl, d, dl)
434435
Sym = SymTridiagonal(d, dl)
435436
F = qr(ones(4, 1))
436437
A = F.Q'
437-
for A in (F.Q, F.Q'), B in (D, Bi, Tri, Sym)
438+
for A in (F.Q, F.Q'), B in (D, Bl, Bu, Tri, Sym)
438439
@test B*A Matrix(B)*A
439440
@test A*B A*Matrix(B)
440441
end

0 commit comments

Comments
 (0)