diff --git a/src/solvers/spqr.jl b/src/solvers/spqr.jl index 2f71dd65..d22dfeda 100644 --- a/src/solvers/spqr.jl +++ b/src/solvers/spqr.jl @@ -45,7 +45,7 @@ function _qr!(ordering::Integer, tol::Real, econ::Integer, getCTX::Integer, E::Union{Ref{Ptr{Ti}} , Ptr{Cvoid}} = C_NULL, H::Union{Ref{Ptr{CHOLMOD.cholmod_sparse}} , Ptr{Cvoid}} = C_NULL, HPinv::Union{Ref{Ptr{Ti}}, Ptr{Cvoid}} = C_NULL, - HTau::Union{Ref{Ptr{CHOLMOD.cholmod_dense}} , Ptr{Cvoid}} = C_NULL) where {Ti<:CHOLMOD.ITypes, Tv<:CHOLMOD.VTypes} + HTau::Union{Ref{Ptr{CHOLMOD.cholmod_dense}} , Ptr{Cvoid}} = C_NULL) where {Ti<:CHOLMOD.ITypes, Tv<:Union{Float64, ComplexF64}} ordering ∈ ORDERINGS || error("unknown ordering $ordering") @@ -208,7 +208,7 @@ Column permutation: [^ACM933]: Foster, L. V., & Davis, T. A. (2013). Algorithm 933: Reliable Calculation of Numerical Rank, Null Space Bases, Pseudoinverse Solutions, and Basic Solutions Using SuitesparseQR. ACM Trans. Math. Softw., 40(1). [doi:10.1145/2513109.2513116](https://doi.org/10.1145/2513109.2513116) """ -function LinearAlgebra.qr(A::SparseMatrixCSC{Tv, Ti}; tol=_default_tol(A), ordering=ORDERING_DEFAULT) where {Ti<:CHOLMOD.ITypes, Tv<:CHOLMOD.VTypes} +function LinearAlgebra.qr(A::SparseMatrixCSC{Tv, Ti}; tol=_default_tol(A), ordering=ORDERING_DEFAULT) where {Ti<:CHOLMOD.ITypes, Tv<:Union{Float64, ComplexF64}} R = Ref{Ptr{CHOLMOD.cholmod_sparse}}() E = Ref{Ptr{Ti}}() H = Ref{Ptr{CHOLMOD.cholmod_sparse}}() @@ -220,9 +220,9 @@ function LinearAlgebra.qr(A::SparseMatrixCSC{Tv, Ti}; tol=_default_tol(A), order C_NULL, C_NULL, C_NULL, C_NULL, R, E, H, HPinv, HTau) - R_ = SparseMatrixCSC{Tv, Ti}(Sparse(R[])) - factors = SparseMatrixCSC{Tv, Ti}(Sparse(H[])) - τ = vec(Array{Tv}(CHOLMOD.Dense(HTau[]))) + R_ = SparseMatrixCSC{Tv, Ti}(Sparse{Tv, Ti}(R[])) + factors = SparseMatrixCSC{Tv, Ti}(Sparse{Tv, Ti}(H[])) + τ = vec(Array{Tv}(CHOLMOD.Dense{Tv}(HTau[]))) R = SparseMatrixCSC{Tv, Ti}(min(size(A)...), size(R_, 2), getcolptr(R_), @@ -235,10 +235,10 @@ function LinearAlgebra.qr(A::SparseMatrixCSC{Tv, Ti}; tol=_default_tol(A), order ReentrantLock(), Tv[]) # _ldiv_workspace (lazily sized on first solve) end -LinearAlgebra.qr(A::SparseMatrixCSC{Float16}; tol=_default_tol(A)) = - QRSparse{Float16}(qr(convert(SparseMatrixCSC{Float32}, A); tol=tol)) -LinearAlgebra.qr(A::SparseMatrixCSC{ComplexF16}; tol=_default_tol(A)) = - QRSparse{ComplexF16}(qr(convert(SparseMatrixCSC{ComplexF32}, A); tol=tol)) +LinearAlgebra.qr(A::SparseMatrixCSC{Tv}; tol=_default_tol(A), ordering=ORDERING_DEFAULT) where {Tv<:Union{Float16, Float32}} = + QRSparse{Tv}(qr(convert(SparseMatrixCSC{Float64}, A); tol, ordering)) +LinearAlgebra.qr(A::SparseMatrixCSC{Tv}; tol=_default_tol(A), ordering=ORDERING_DEFAULT) where {Tv<:Union{ComplexF16, ComplexF32}} = + QRSparse{Tv}(qr(convert(SparseMatrixCSC{ComplexF64}, A); tol, ordering)) LinearAlgebra.qr(A::Union{SparseMatrixCSC{T},SparseMatrixCSC{Complex{T}}}; tol=_default_tol(A)) where {T<:AbstractFloat} = throw(ArgumentError(string("matrix type ", typeof(A), "not supported. ", diff --git a/test/spqr.jl b/test/spqr.jl index f12b68d3..8227457c 100644 --- a/test/spqr.jl +++ b/test/spqr.jl @@ -116,6 +116,16 @@ end @test eltype(F.Q) == eltype(F.R) == eltyA end +@testset "single-precision qr factorization works as expected: $eltyA" for eltyA in (Float32, ComplexF32, Float16, ComplexF16) + seed!(4) + A = SparseMatrixCSC{eltyA, Int}(eltyA <: Real ? sprandn(m, n, 0.3) : sprandn(ComplexF64, m, n, 0.3)) + F = qr(A) + @test eltype(F.Q) == eltype(F.R) == eltyA + @test Matrix(F.Q) * F.R ≈ A[F.prow, F.pcol] + x = ones(eltyA, n) + @test F \ (A * x) ≈ x +end + @testset "select ordering overdetermined" begin A = sparse([1:n; rand(1:m, nn - n)], [1:n; rand(1:n, nn - n)], randn(nn), m, n) b = randn(m)