Skip to content

Commit

Permalink
Consolidate the \ methods for sparse and dense and make the necessary…
Browse files Browse the repository at this point in the history
… adjustment

to other methods.

Solve real lhs problems with complex rhs by reinterpreting the rhs.

Let factorize(SparseMatrixCSC) check for tringular matrices
  • Loading branch information
andreasnoack committed Nov 1, 2015
1 parent 81753cc commit 87e26c5
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 37 deletions.
14 changes: 0 additions & 14 deletions base/linalg/dense.jl
Original file line number Diff line number Diff line change
Expand Up @@ -436,20 +436,6 @@ function factorize{T}(A::Matrix{T})
qrfact(A, Val{true})
end

(\)(a::Vector, B::StridedVecOrMat) = (\)(reshape(a, length(a), 1), B)

function (\)(A::StridedMatrix, B::StridedVecOrMat)
m, n = size(A)
if m == n
if istril(A)
return istriu(A) ? \(Diagonal(A),B) : \(LowerTriangular(A),B)
end
istriu(A) && return \(UpperTriangular(A),B)
return \(lufact(A),B)
end
return qrfact(A,Val{true})\B
end

## Moore-Penrose pseudoinverse
function pinv{T}(A::StridedMatrix{T}, tol::Real)
m, n = size(A)
Expand Down
8 changes: 4 additions & 4 deletions base/linalg/diagonal.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
immutable Diagonal{T} <: AbstractMatrix{T}
diag::Vector{T}
end
Diagonal(A::Matrix) = Diagonal(diag(A))
Diagonal(A::AbstractMatrix) = Diagonal(diag(A))

convert{T}(::Type{Diagonal{T}}, D::Diagonal{T}) = D
convert{T}(::Type{Diagonal{T}}, D::Diagonal) = Diagonal{T}(convert(Vector{T}, D.diag))
Expand Down Expand Up @@ -163,9 +163,9 @@ function A_ldiv_B!(D::Diagonal, B::StridedVecOrMat)
end
return B
end
\(D::Diagonal, B::StridedMatrix) = scale(1 ./ D.diag, B)
\(D::Diagonal, b::StridedVector) = reshape(scale(1 ./ D.diag, reshape(b, length(b), 1)), length(b))
\(Da::Diagonal, Db::Diagonal) = Diagonal(Db.diag ./ Da.diag)
(\)(D::Diagonal, B::AbstractMatrix) = scale(1 ./ D.diag, B)
(\)(D::Diagonal, b::AbstractVector) = reshape(scale(1 ./ D.diag, reshape(b, length(b), 1)), length(b))
(\)(Da::Diagonal, Db::Diagonal) = Diagonal(Db.diag ./ Da.diag)

function inv{T}(D::Diagonal{T})
Di = similar(D.diag)
Expand Down
16 changes: 15 additions & 1 deletion base/linalg/factorization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,21 @@ end
### General promotion rules
convert{T}(::Type{Factorization{T}}, F::Factorization{T}) = F
inv{T}(F::Factorization{T}) = A_ldiv_B!(F, eye(T, size(F,1)))
function \{TF<:Number,TB<:Number,N}(F::Factorization{TF}, B::AbstractArray{TB,N})

# With a real lhs and complex rhs with the same precision, we can reinterpret
# the complex rhs as a real rhs with twice the number of columns
function (\){T<:BlasReal}(F::Factorization{T}, B::AbstractVector{Complex{T}})
c2r = reshape(transpose(reinterpret(T, B, (2, length(B)))), size(B, 1), 2*size(B, 2))
x = A_ldiv_B!(F, c2r)
return reinterpret(Complex{T}, transpose(reshape(x, div(length(x), 2), 2)), (size(F,2),))
end
function (\){T<:BlasReal}(F::Factorization{T}, B::AbstractMatrix{Complex{T}})
c2r = reshape(transpose(reinterpret(T, B, (2, length(B)))), size(B, 1), 2*size(B, 2))
x = A_ldiv_B!(F, c2r)
return reinterpret(Complex{T}, transpose(reshape(x, div(length(x), 2), 2)), (size(F,2), size(B,2)))
end

function (\){TF<:Number,TB<:Number,N}(F::Factorization{TF}, B::AbstractArray{TB,N})
TFB = typeof(one(TF)/one(TB))
A_ldiv_B!(convert(Factorization{TFB}, F), copy_oftype(B, TFB))
end
Expand Down
27 changes: 17 additions & 10 deletions base/linalg/generic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -325,19 +325,26 @@ function inv{T}(A::AbstractMatrix{T})
A_ldiv_B!(factorize(convert(AbstractMatrix{S}, A)), eye(S, chksquare(A)))
end

function \{T}(A::AbstractMatrix{T}, B::AbstractVecOrMat{T})
if size(A,1) != size(B,1)
throw(DimensionMismatch("left and right hand sides should have the same number of rows, left hand side has $(size(A,1)) rows, but right hand side has $(size(B,1)) rows."))
function (\)(A::AbstractMatrix, B::AbstractVecOrMat)
m, n = size(A)
if m == n
if istril(A)
if istriu(A)
return Diagonal(A) \ B
else
return LowerTriangular(A) \ B
end
end
if istriu(A)
return UpperTriangular(A) \ B
end
return lufact(A) \ B
end
factorize(A)\B
end
function \{TA,TB}(A::AbstractMatrix{TA}, B::AbstractVecOrMat{TB})
TC = typeof(one(TA)/one(TB))
convert(AbstractMatrix{TC}, A)\convert(AbstractArray{TC}, B)
return qrfact(A,Val{true}) \ B
end

\(a::AbstractVector, b::AbstractArray) = reshape(a, length(a), 1) \ b
/(A::AbstractVecOrMat, B::AbstractVecOrMat) = (B' \ A')'
(\)(a::AbstractVector, b::AbstractArray) = reshape(a, length(a), 1) \ b
(/)(A::AbstractVecOrMat, B::AbstractVecOrMat) = (B' \ A')'
# \(A::StridedMatrix,x::Number) = inv(A)*x Should be added at some point when the old elementwise version has been deprecated long enough
# /(x::Number,A::StridedMatrix) = x*inv(A)

Expand Down
9 changes: 9 additions & 0 deletions base/sparse/linalg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,15 @@ scale{T,Tv,Ti}(b::Vector{T}, A::SparseMatrixCSC{Tv,Ti}) =
function factorize(A::SparseMatrixCSC)
m, n = size(A)
if m == n
if istril(A)
if istriu(A)
return return Diagonal(A)
else
return LowerTriangular(A)
end
elseif istriu(A)
return UpperTriangular(A)
end
AC = CHOLMOD.Sparse(A)
if ishermitian(AC)
try
Expand Down
24 changes: 20 additions & 4 deletions base/sparse/spqr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,28 @@ function qmult{Tv<:VTypes}(method::Integer, QR::Factorization{Tv}, X::Dense{Tv})
d
end

qrfact(A::SparseMatrixCSC) = factorize(ORDERING_DEFAULT, DEFAULT_TOL, Sparse(A, 0))

function (\){T}(F::Factorization{T}, B::StridedVecOrMat{T})
qrfact(A::SparseMatrixCSC, ::Type{Val{true}}) = factorize(ORDERING_DEFAULT, DEFAULT_TOL, Sparse(A, 0))
qrfact(A::SparseMatrixCSC) = qrfact(A, Val{true})

# With a real lhs and complex rhs with the same precision, we can reinterpret
# the complex rhs as a real rhs with twice the number of columns
#
# This definition is similar to the definition in factorization.jl except the we here have to use
# \ instead of A_ldiv_B! because of limitations in SPQR
function (\)(F::Factorization{Float64}, B::StridedVector{Complex{Float64}})
c2r = reshape(transpose(reinterpret(Float64, B, (2, length(B)))), size(B, 1), 2*size(B, 2))
x = F\c2r
return reinterpret(Complex{Float64}, transpose(reshape(x, div(length(x), 2), 2)), (size(F,2),))
end
function (\)(F::Factorization{Float64}, B::StridedMatrix{Complex{Float64}})
c2r = reshape(transpose(reinterpret(Float64, B, (2, length(B)))), size(B, 1), 2*size(B, 2))
x = F\c2r
return reinterpret(Complex{Float64}, transpose(reshape(x, div(length(x), 2), 2)), (size(F,2), size(B,2)))
end
function (\){T<:VTypes}(F::Factorization{T}, B::StridedVecOrMat{T})
QtB = qmult(QTX, F, Dense(B))
convert(typeof(B), solve(RETX_EQUALS_B, F, QtB))
end
(\){T,S}(F::Factorization{T}, B::StridedVecOrMat{S}) = F\convert(AbstractArray{T}, B)
(\)(F::Factorization, B::StridedVecOrMat) = F\convert(AbstractArray{eltype(F)}, B)

end # module
19 changes: 16 additions & 3 deletions base/sparse/umfpack.jl
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,22 @@ function lufact{Tv<:UMFVTypes,Ti<:UMFITypes}(S::SparseMatrixCSC{Tv,Ti})
end
lufact(A::SparseMatrixCSC) = lufact(float(A))

function show(io::IO, f::UmfpackLU)
println(io, "UMFPACK LU Factorization of a $(f.m)-by-$(f.n) sparse matrix")
f.numeric != C_NULL && println(io, f.numeric)
size(F::UmfpackLU) = (F.m, F.n)
function size(F::UmfpackLU, dim::Integer)
if dim < 1
error("arraysize: dimension out of range")
elseif dim == 1
return Int(F.m)
elseif dim == 2
return Int(F.n)
else
return 1
end
end

function show(io::IO, F::UmfpackLU)
println(io, "UMFPACK LU Factorization of a $(size(F)) sparse matrix")
F.numeric != C_NULL && println(io, F.numeric)
end

## Wrappers for UMFPACK functions
Expand Down
1 change: 0 additions & 1 deletion test/sparsedir/cholmod.jl
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,6 @@ let # Issue 9160
end
end


# Issue #9915
@test speye(2)\speye(2) == eye(2)

Expand Down

0 comments on commit 87e26c5

Please sign in to comment.