Skip to content

Commit

Permalink
Merge pull request #24170 from Sacha0/similarstruc
Browse files Browse the repository at this point in the history
make similar(A, [T,] shape...) for structured A yield a sparse rather than dense array
  • Loading branch information
Sacha0 committed Oct 20, 2017
2 parents 940c770 + 056d6f6 commit 40607f9
Show file tree
Hide file tree
Showing 9 changed files with 44 additions and 24 deletions.
7 changes: 6 additions & 1 deletion base/linalg/bidiag.jl
Expand Up @@ -170,7 +170,12 @@ convert(::Type{AbstractMatrix{T}}, A::Bidiagonal) where {T} = convert(Bidiagonal

broadcast(::typeof(big), B::Bidiagonal) = Bidiagonal(big.(B.dv), big.(B.ev), B.uplo)

similar(B::Bidiagonal, ::Type{T}) where {T} = Bidiagonal{T}(similar(B.dv, T), similar(B.ev, T), B.uplo)
# For B<:Bidiagonal, similar(B[, neweltype]) should yield a Bidiagonal matrix.
# On the other hand, similar(B, [neweltype,] shape...) should yield a sparse matrix.
# The first method below effects the former, and the second the latter.
similar(B::Bidiagonal, ::Type{T}) where {T} = Bidiagonal(similar(B.dv, T), similar(B.ev, T), B.uplo)
similar(B::Bidiagonal, ::Type{T}, dims::Union{Dims{1},Dims{2}}) where {T} = spzeros(T, dims...)


###################
# LAPACK routines #
Expand Down
13 changes: 10 additions & 3 deletions base/linalg/diagonal.jl
Expand Up @@ -56,9 +56,11 @@ convert(::Type{Matrix}, D::Diagonal) = diagm(0 => D.diag)
convert(::Type{Array}, D::Diagonal) = convert(Matrix, D)
full(D::Diagonal) = convert(Array, D)

function similar(D::Diagonal, ::Type{T}) where T
return Diagonal{T}(similar(D.diag, T))
end
# For D<:Diagonal, similar(D[, neweltype]) should yield a Diagonal matrix.
# On the other hand, similar(D, [neweltype,] shape...) should yield a sparse matrix.
# The first method below effects the former, and the second the latter.
similar(D::Diagonal, ::Type{T}) where {T} = Diagonal(similar(D.diag, T))
similar(D::Diagonal, ::Type{T}, dims::Union{Dims{1},Dims{2}}) where {T} = spzeros(T, dims...)

copy!(D1::Diagonal, D2::Diagonal) = (copy!(D1.diag, D2.diag); D1)

Expand Down Expand Up @@ -305,6 +307,11 @@ end
A_rdiv_Bc!(A::AbstractMatrix{T}, D::Diagonal{T}) where {T} = A_rdiv_B!(A, conj(D))
A_rdiv_Bt!(A::AbstractMatrix{T}, D::Diagonal{T}) where {T} = A_rdiv_B!(A, D)

(\)(F::Factorization, D::Diagonal) =
A_ldiv_B!(F, Matrix{typeof(oneunit(eltype(D))/oneunit(eltype(F)))}(D))
Ac_ldiv_B(F::Factorization, D::Diagonal) =
Ac_ldiv_B!(F, Matrix{typeof(oneunit(eltype(D))/oneunit(eltype(F)))}(D))

# Methods to resolve ambiguities with `Diagonal`
@inline *(rowvec::RowVector, D::Diagonal) = transpose(D * transpose(rowvec))
@inline A_mul_Bt(D::Diagonal, rowvec::RowVector) = D*transpose(rowvec)
Expand Down
6 changes: 3 additions & 3 deletions base/linalg/lu.jl
Expand Up @@ -140,20 +140,20 @@ true
"""
function lufact(A::AbstractMatrix{T}, pivot::Union{Val{false}, Val{true}}) where T
S = typeof(zero(T)/one(T))
AA = similar(A, S, size(A))
AA = similar(A, S)
copy!(AA, A)
lufact!(AA, pivot)
end
# We can't assume an ordered field so we first try without pivoting
function lufact(A::AbstractMatrix{T}) where T
S = typeof(zero(T)/one(T))
AA = similar(A, S, size(A))
AA = similar(A, S)
copy!(AA, A)
F = lufact!(AA, Val(false))
if issuccess(F)
return F
else
AA = similar(A, S, size(A))
AA = similar(A, S)
copy!(AA, A)
return lufact!(AA, Val(true))
end
Expand Down
6 changes: 3 additions & 3 deletions base/linalg/special.jl
Expand Up @@ -52,13 +52,13 @@ convert(::Type{Diagonal}, A::AbstractTriangular) =
isdiag(A) ? Diagonal(diag(A)) :
throw(ArgumentError("matrix cannot be represented as Diagonal"))
convert(::Type{Bidiagonal}, A::AbstractTriangular) =
isbanded(A, 0, 1) ? Bidiagonal(diag(A), diag(A, 1), :U) : # is upper bidiagonal
isbanded(A, -1, 0) ? Bidiagonal(diag(A), diag(A, -1), :L) : # is lower bidiagonal
isbanded(A, 0, 1) ? Bidiagonal(diag(A, 0), diag(A, 1), :U) : # is upper bidiagonal
isbanded(A, -1, 0) ? Bidiagonal(diag(A, 0), diag(A, -1), :L) : # is lower bidiagonal
throw(ArgumentError("matrix cannot be represented as Bidiagonal"))
convert(::Type{SymTridiagonal}, A::AbstractTriangular) =
convert(SymTridiagonal, convert(Tridiagonal, A))
convert(::Type{Tridiagonal}, A::AbstractTriangular) =
isbanded(A, -1, 1) ? Tridiagonal(diag(A, -1), diag(A), diag(A, 1)) : # is tridiagonal
isbanded(A, -1, 1) ? Tridiagonal(diag(A, -1), diag(A, 0), diag(A, 1)) : # is tridiagonal
throw(ArgumentError("matrix cannot be represented as Tridiagonal"))


Expand Down
6 changes: 1 addition & 5 deletions base/linalg/triangular.jl
Expand Up @@ -1434,11 +1434,7 @@ end

## Some Triangular-Triangular cases. We might want to write taylored methods
## for these cases, but I'm not sure it is worth it.
for t in (UpperTriangular, UnitUpperTriangular, LowerTriangular, UnitLowerTriangular)
@eval begin
(*)(A::Tridiagonal, B::$t) = A_mul_B!(Matrix(A), B)
end
end
(*)(A::Union{Tridiagonal,SymTridiagonal}, B::AbstractTriangular) = A_mul_B!(Matrix(A), B)

for (f1, f2) in ((:*, :A_mul_B!), (:\, :A_ldiv_B!))
@eval begin
Expand Down
15 changes: 11 additions & 4 deletions base/linalg/tridiag.jl
Expand Up @@ -108,7 +108,11 @@ function size(A::SymTridiagonal, d::Integer)
end
end

similar(S::SymTridiagonal, ::Type{T}) where {T} = SymTridiagonal{T}(similar(S.dv, T), similar(S.ev, T))
# For S<:SymTridiagonal, similar(S[, neweltype]) should yield a SymTridiagonal matrix.
# On the other hand, similar(S, [neweltype,] shape...) should yield a sparse matrix.
# The first method below effects the former, and the second the latter.
similar(S::SymTridiagonal, ::Type{T}) where {T} = SymTridiagonal(similar(S.dv, T), similar(S.ev, T))
similar(S::SymTridiagonal, ::Type{T}, dims::Union{Dims{1},Dims{2}}) where {T} = spzeros(T, dims...)

#Elementary operations
broadcast(::typeof(abs), M::SymTridiagonal) = SymTridiagonal(abs.(M.dv), abs.(M.ev))
Expand Down Expand Up @@ -499,9 +503,12 @@ end
convert(::Type{Matrix}, M::Tridiagonal{T}) where {T} = convert(Matrix{T}, M)
convert(::Type{Array}, M::Tridiagonal) = convert(Matrix, M)
full(M::Tridiagonal) = convert(Array, M)
function similar(M::Tridiagonal, ::Type{T}) where T
Tridiagonal{T}(similar(M.dl, T), similar(M.d, T), similar(M.du, T))
end

# For M<:Tridiagonal, similar(M[, neweltype]) should yield a Tridiagonal matrix.
# On the other hand, similar(M, [neweltype,] shape...) should yield a sparse matrix.
# The first method below effects the former, and the second the latter.
similar(M::Tridiagonal, ::Type{T}) where {T} = Tridiagonal(similar(M.dl, T), similar(M.d, T), similar(M.du, T))
similar(M::Tridiagonal, ::Type{T}, dims::Union{Dims{1},Dims{2}}) where {T} = spzeros(T, dims...)

# Operations on Tridiagonal matrices
copy!(dest::Tridiagonal, src::Tridiagonal) = (copy!(dest.dl, src.dl); copy!(dest.d, src.d); copy!(dest.du, src.du); dest)
Expand Down
5 changes: 4 additions & 1 deletion test/linalg/bidiag.jl
Expand Up @@ -78,8 +78,11 @@ srand(1)
@test size(ubd, 3) == 1
# bidiagonal similar
@test isa(similar(ubd), Bidiagonal{elty})
@test similar(ubd).uplo == ubd.uplo
@test isa(similar(ubd, Int), Bidiagonal{Int})
@test isa(similar(ubd, Int, (3, 2)), Matrix{Int})
@test similar(ubd, Int).uplo == ubd.uplo
@test isa(similar(ubd, (3, 2)), SparseMatrixCSC)
@test isa(similar(ubd, Int, (3, 2)), SparseMatrixCSC{Int})
end

@testset "show" begin
Expand Down
4 changes: 2 additions & 2 deletions test/linalg/diagonal.jl
Expand Up @@ -228,8 +228,8 @@ srand(1)
@testset "similar" begin
@test isa(similar(D), Diagonal{elty})
@test isa(similar(D, Int), Diagonal{Int})
@test isa(similar(D, (3,2)), Matrix{elty})
@test isa(similar(D, Int, (3,2)), Matrix{Int})
@test isa(similar(D, (3,2)), SparseMatrixCSC{elty})
@test isa(similar(D, Int, (3,2)), SparseMatrixCSC{Int})
end

# Issue number 10036
Expand Down
6 changes: 4 additions & 2 deletions test/linalg/tridiag.jl
Expand Up @@ -125,7 +125,8 @@ guardsrand(123) do
end
@test isa(similar(A), mat_type{elty})
@test isa(similar(A, Int), mat_type{Int})
@test isa(similar(A, Int, (3, 2)), Matrix{Int})
@test isa(similar(A, (3, 2)), SparseMatrixCSC)
@test isa(similar(A, Int, (3, 2)), SparseMatrixCSC{Int})
@test size(A, 3) == 1
@test size(A, 1) == n
@test size(A) == (n, n)
Expand Down Expand Up @@ -290,7 +291,8 @@ guardsrand(123) do
@testset "similar" begin
@test isa(similar(Ts), SymTridiagonal{elty})
@test isa(similar(Ts, Int), SymTridiagonal{Int})
@test isa(similar(Ts, Int, (3,2)), Matrix{Int})
@test isa(similar(Ts, (3, 2)), SparseMatrixCSC)
@test isa(similar(Ts, Int, (3, 2)), SparseMatrixCSC{Int})
end

@test first(logabsdet(Tldlt)) first(logabsdet(Fs))
Expand Down

0 comments on commit 40607f9

Please sign in to comment.