diff --git a/NEWS.md b/NEWS.md index a5fd03a00ca72a..fa94eee055a6df 100644 --- a/NEWS.md +++ b/NEWS.md @@ -704,9 +704,9 @@ Deprecated or removed `type` is fully deprecated to `mutable struct` ([#19157], [#20418]). * `lufact`, `schurfact`, `lqfact`, `qrfact`, `ldltfact`, `svdfact`, - `bkfact`, `hessfact`, and `eigfact` have respectively been deprecated to - `lu`, `schur`, `lq`, `qr`, `ldlt`, `svd`, `bunchkaufman`, - `hessenberg`, and `eigen` ([#27159]). + `bkfact`, `hessfact`, `eigfact`, and `cholfact` have respectively been + deprecated to `lu`, `schur`, `lq`, `qr`, `ldlt`, `svd`, `bunchkaufman`, + `hessenberg`, `eigen`, and `cholesky` ([#27159]). * `lufact!`, `schurfact!`, `lqfact!`, `qrfact!`, `ldltfact!`, `svdfact!`, `bkfact!`, `hessfact!`, and `eigfact!` have respectively been deprecated to diff --git a/stdlib/LinearAlgebra/docs/src/index.md b/stdlib/LinearAlgebra/docs/src/index.md index 5b081e7aeefdf1..9e881a7db1d8f6 100644 --- a/stdlib/LinearAlgebra/docs/src/index.md +++ b/stdlib/LinearAlgebra/docs/src/index.md @@ -314,7 +314,7 @@ LinearAlgebra.UniformScaling LinearAlgebra.lu LinearAlgebra.lu! LinearAlgebra.chol -LinearAlgebra.cholfact +LinearAlgebra.cholesky LinearAlgebra.cholfact! LinearAlgebra.lowrankupdate LinearAlgebra.lowrankdowndate diff --git a/stdlib/LinearAlgebra/src/LinearAlgebra.jl b/stdlib/LinearAlgebra/src/LinearAlgebra.jl index a6770d3c6e9600..9ff0b1c0836f08 100644 --- a/stdlib/LinearAlgebra/src/LinearAlgebra.jl +++ b/stdlib/LinearAlgebra/src/LinearAlgebra.jl @@ -66,7 +66,7 @@ export bunchkaufman, bunchkaufman!, chol, - cholfact, + cholesky, cholfact!, cond, condskeel, @@ -250,7 +250,7 @@ end Compute `A \\ B` in-place and store the result in `Y`, returning the result. The argument `A` should *not* be a matrix. Rather, instead of matrices it should be a -factorization object (e.g. produced by [`factorize`](@ref) or [`cholfact`](@ref)). +factorization object (e.g. produced by [`factorize`](@ref) or [`cholesky`](@ref)). The reason for this is that factorization itself is both expensive and typically allocates memory (although it can also be done in-place via, e.g., [`lu!`](@ref)), and performance-critical situations requiring `ldiv!` usually also require fine-grained @@ -264,7 +264,7 @@ ldiv!(Y, A, B) Compute `A \\ B` in-place and overwriting `B` to store the result. The argument `A` should *not* be a matrix. Rather, instead of matrices it should be a -factorization object (e.g. produced by [`factorize`](@ref) or [`cholfact`](@ref)). +factorization object (e.g. produced by [`factorize`](@ref) or [`cholesky`](@ref)). The reason for this is that factorization itself is both expensive and typically allocates memory (although it can also be done in-place via, e.g., [`lu!`](@ref)), and performance-critical situations requiring `ldiv!` usually also require fine-grained @@ -279,7 +279,7 @@ ldiv!(A, B) Compute `A / B` in-place and overwriting `A` to store the result. The argument `B` should *not* be a matrix. Rather, instead of matrices it should be a -factorization object (e.g. produced by [`factorize`](@ref) or [`cholfact`](@ref)). +factorization object (e.g. produced by [`factorize`](@ref) or [`cholesky`](@ref)). The reason for this is that factorization itself is both expensive and typically allocates memory (although it can also be done in-place via, e.g., [`lu!`](@ref)), and performance-critical situations requiring `rdiv!` usually also require fine-grained diff --git a/stdlib/LinearAlgebra/src/cholesky.jl b/stdlib/LinearAlgebra/src/cholesky.jl index 0b4de8cc6e3120..223a10d158a74e 100644 --- a/stdlib/LinearAlgebra/src/cholesky.jl +++ b/stdlib/LinearAlgebra/src/cholesky.jl @@ -4,14 +4,14 @@ # Cholesky Factorization # ########################## -# The dispatch structure in the chol!, chol, cholfact, and cholfact! methods is a bit +# The dispatch structure in the chol!, chol, cholesky, and cholfact! methods is a bit # complicated and some explanation is therefore provided in the following # # In the methods below, LAPACK is called when possible, i.e. StridedMatrices with Float32, # Float64, Complex{Float32}, and Complex{Float64} element types. For other element or -# matrix types, the unblocked Julia implementation in _chol! is used. For cholfact +# matrix types, the unblocked Julia implementation in _chol! is used. For cholesky # and cholfact! pivoting is supported through a Val(Bool) argument. A type argument is -# necessary for type stability since the output of cholfact and cholfact! is either +# necessary for type stability since the output of cholesky and cholfact! is either # Cholesky or PivotedCholesky. The latter is only # supported for the four LAPACK element types. For other types, e.g. BigFloats Val(true) will # give an error. It is required that the input is Hermitian (including real symmetric) either @@ -21,7 +21,7 @@ # The internal structure is as follows # - _chol! returns the factor and info without checking positive definiteness # - chol/chol! returns the factor and checks for positive definiteness -# - cholfact/cholfact! returns Cholesky without checking positive definiteness +# - cholesky/cholfact! returns Cholesky without checking positive definiteness # FixMe? The dispatch below seems overly complicated. One simplification could be to # merge the two Cholesky types into one. It would remove the need for Val completely but @@ -218,7 +218,7 @@ end """ cholfact!(A, Val(false)) -> Cholesky -The same as [`cholfact`](@ref), but saves space by overwriting the input `A`, +The same as [`cholesky`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. An [`InexactError`](@ref) exception is thrown if the factorization produces a number not representable by the element type of `A`, e.g. for integer types. @@ -263,7 +263,7 @@ cholfact!(A::RealHermSymComplexHerm{<:Real}, ::Val{true}; tol = 0.0) = """ cholfact!(A, Val(true); tol = 0.0) -> CholeskyPivoted -The same as [`cholfact`](@ref), but saves space by overwriting the input `A`, +The same as [`cholesky`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. An [`InexactError`](@ref) exception is thrown if the factorization produces a number not representable by the element type of `A`, e.g. for integer types. @@ -278,11 +278,11 @@ function cholfact!(A::StridedMatrix, ::Val{true}; tol = 0.0) end end -# cholfact. Non-destructive methods for computing Cholesky factorization of real symmetric +# cholesky. Non-destructive methods for computing Cholesky factorization of real symmetric # or Hermitian matrix ## No pivoting (default) """ - cholfact(A, Val(false)) -> Cholesky + cholesky(A, Val(false)) -> Cholesky Compute the Cholesky factorization of a dense symmetric positive definite matrix `A` and return a `Cholesky` factorization. The matrix `A` can either be a [`Symmetric`](@ref) or [`Hermitian`](@ref) @@ -299,7 +299,7 @@ julia> A = [4. 12. -16.; 12. 37. -43.; -16. -43. 98.] 12.0 37.0 -43.0 -16.0 -43.0 98.0 -julia> C = cholfact(A) +julia> C = cholesky(A) Cholesky{Float64,Array{Float64,2}} U factor: 3×3 UpperTriangular{Float64,Array{Float64,2}}: @@ -323,13 +323,13 @@ julia> C.L * C.U == A true ``` """ -cholfact(A::Union{StridedMatrix,RealHermSymComplexHerm{<:Real,<:StridedMatrix}}, +cholesky(A::Union{StridedMatrix,RealHermSymComplexHerm{<:Real,<:StridedMatrix}}, ::Val{false}=Val(false)) = cholfact!(cholcopy(A)) ## With pivoting """ - cholfact(A, Val(true); tol = 0.0) -> CholeskyPivoted + cholesky(A, Val(true); tol = 0.0) -> CholeskyPivoted Compute the pivoted Cholesky factorization of a dense symmetric positive semi-definite matrix `A` and return a `CholeskyPivoted` factorization. The matrix `A` can either be a [`Symmetric`](@ref) @@ -340,11 +340,11 @@ The following functions are available for `PivotedCholesky` objects: The argument `tol` determines the tolerance for determining the rank. For negative values, the tolerance is the machine precision. """ -cholfact(A::Union{StridedMatrix,RealHermSymComplexHerm{<:Real,<:StridedMatrix}}, +cholesky(A::Union{StridedMatrix,RealHermSymComplexHerm{<:Real,<:StridedMatrix}}, ::Val{true}; tol = 0.0) = cholfact!(cholcopy(A), Val(true); tol = tol) ## Number -function cholfact(x::Number, uplo::Symbol=:U) +function cholesky(x::Number, uplo::Symbol=:U) C, info = _chol!(x, uplo) xf = fill(C, 1, 1) Cholesky(xf, uplo, info) @@ -557,7 +557,7 @@ rank(C::CholeskyPivoted) = C.rank lowrankupdate!(C::Cholesky, v::StridedVector) -> CC::Cholesky Update a Cholesky factorization `C` with the vector `v`. If `A = C.U'C.U` then -`CC = cholfact(C.U'C.U + v*v')` but the computation of `CC` only uses `O(n^2)` +`CC = cholesky(C.U'C.U + v*v')` but the computation of `CC` only uses `O(n^2)` operations. The input factorization `C` is updated in place such that on exit `C == CC`. The vector `v` is destroyed during the computation. """ @@ -603,7 +603,7 @@ end lowrankdowndate!(C::Cholesky, v::StridedVector) -> CC::Cholesky Downdate a Cholesky factorization `C` with the vector `v`. If `A = C.U'C.U` then -`CC = cholfact(C.U'C.U - v*v')` but the computation of `CC` only uses `O(n^2)` +`CC = cholesky(C.U'C.U - v*v')` but the computation of `CC` only uses `O(n^2)` operations. The input factorization `C` is updated in place such that on exit `C == CC`. The vector `v` is destroyed during the computation. """ @@ -656,7 +656,7 @@ end lowrankupdate(C::Cholesky, v::StridedVector) -> CC::Cholesky Update a Cholesky factorization `C` with the vector `v`. If `A = C.U'C.U` -then `CC = cholfact(C.U'C.U + v*v')` but the computation of `CC` only uses +then `CC = cholesky(C.U'C.U + v*v')` but the computation of `CC` only uses `O(n^2)` operations. """ lowrankupdate(C::Cholesky, v::StridedVector) = lowrankupdate!(copy(C), copy(v)) @@ -665,7 +665,7 @@ lowrankupdate(C::Cholesky, v::StridedVector) = lowrankupdate!(copy(C), copy(v)) lowrankdowndate(C::Cholesky, v::StridedVector) -> CC::Cholesky Downdate a Cholesky factorization `C` with the vector `v`. If `A = C.U'C.U` -then `CC = cholfact(C.U'C.U - v*v')` but the computation of `CC` only uses +then `CC = cholesky(C.U'C.U - v*v')` but the computation of `CC` only uses `O(n^2)` operations. """ lowrankdowndate(C::Cholesky, v::StridedVector) = lowrankdowndate!(copy(C), copy(v)) diff --git a/stdlib/LinearAlgebra/src/dense.jl b/stdlib/LinearAlgebra/src/dense.jl index 312ef17fb3c0af..0420dfd86c51ee 100644 --- a/stdlib/LinearAlgebra/src/dense.jl +++ b/stdlib/LinearAlgebra/src/dense.jl @@ -109,7 +109,7 @@ julia> isposdef(A) true ``` """ -isposdef(A::AbstractMatrix) = ishermitian(A) && isposdef(cholfact(Hermitian(A))) +isposdef(A::AbstractMatrix) = ishermitian(A) && isposdef(cholesky(Hermitian(A))) isposdef(x::Number) = imag(x)==0 && real(x) > 0 # the definition of strides for Array{T,N} is tuple() if N = 0, otherwise it is @@ -1112,7 +1112,7 @@ systems. For example: `A=factorize(A); x=A\\b; y=A\\C`. | Properties of `A` | type of factorization | |:---------------------------|:-----------------------------------------------| -| Positive-definite | Cholesky (see [`cholfact`](@ref)) | +| Positive-definite | Cholesky (see [`cholesky`](@ref)) | | Dense Symmetric/Hermitian | Bunch-Kaufman (see [`bunchkaufman`](@ref)) | | Sparse Symmetric/Hermitian | LDLt (see [`ldlt`](@ref)) | | Triangular | Triangular | @@ -1208,7 +1208,7 @@ function factorize(A::StridedMatrix{T}) where T return UpperTriangular(A) end if herm - cf = cholfact(A) + cf = cholesky(A) if cf.info == 0 return cf else diff --git a/stdlib/LinearAlgebra/src/deprecated.jl b/stdlib/LinearAlgebra/src/deprecated.jl index fea7008320ebb8..f374af9b0094ef 100644 --- a/stdlib/LinearAlgebra/src/deprecated.jl +++ b/stdlib/LinearAlgebra/src/deprecated.jl @@ -7,6 +7,7 @@ using Base: @deprecate, depwarn @deprecate cond(F::LinearAlgebra.LU, p::Integer) cond(convert(AbstractArray, F), p) # PR #22188 +export cholfact @deprecate cholfact!(A::StridedMatrix, uplo::Symbol, ::Type{Val{false}}) cholfact!(Hermitian(A, uplo), Val(false)) @deprecate cholfact!(A::StridedMatrix, uplo::Symbol) cholfact!(Hermitian(A, uplo)) @deprecate cholfact(A::StridedMatrix, uplo::Symbol, ::Type{Val{false}}) cholfact(Hermitian(A, uplo), Val(false)) @@ -1395,3 +1396,9 @@ export eigfact! @deprecate(eigfact!(A::RealHermSymComplexHerm{T,<:StridedMatrix}, vl::Real, vh::Real) where {T<:BlasReal}, eigen!(A, vl, vh)) @deprecate(eigfact!(A::HermOrSym{T,S}, B::HermOrSym{T,S}) where {T<:BlasReal,S<:StridedMatrix}, eigen!(A, B)) @deprecate(eigfact!(A::Hermitian{T,S}, B::Hermitian{T,S}) where {T<:BlasComplex,S<:StridedMatrix}, eigen!(A, B)) + +# deprecate cholfact to cholesky +# cholfact exported from deprecation above +@deprecate(cholfact(A::Union{StridedMatrix,RealHermSymComplexHerm{<:Real,<:StridedMatrix}}, ::Val{false}=Val(false)), cholesky(A, Val(false))) +@deprecate(cholfact(A::Union{StridedMatrix,RealHermSymComplexHerm{<:Real,<:StridedMatrix}}, ::Val{true}; tol = 0.0), cholesky(A, Val(true); tol=tol)) +@deprecate(cholfact(x::Number, uplo::Symbol=:U), cholesky(x, uplo)) diff --git a/stdlib/LinearAlgebra/src/factorization.jl b/stdlib/LinearAlgebra/src/factorization.jl index b0674ae64f6832..9dadfc08cf9cd7 100644 --- a/stdlib/LinearAlgebra/src/factorization.jl +++ b/stdlib/LinearAlgebra/src/factorization.jl @@ -22,7 +22,7 @@ end Test that a factorization of a matrix succeeded. ```jldoctest -julia> F = cholfact([1 0; 0 1]); +julia> F = cholesky([1 0; 0 1]); julia> LinearAlgebra.issuccess(F) true diff --git a/stdlib/LinearAlgebra/test/bunchkaufman.jl b/stdlib/LinearAlgebra/test/bunchkaufman.jl index 8469196b7dc0eb..5bd345afe6c5df 100644 --- a/stdlib/LinearAlgebra/test/bunchkaufman.jl +++ b/stdlib/LinearAlgebra/test/bunchkaufman.jl @@ -132,7 +132,7 @@ end @testset "test example due to @timholy in PR 15354" begin A = rand(6,5); A = complex(A'*A) # to avoid calling the real-lhs-complex-rhs method - F = cholfact(A); + F = cholesky(A); v6 = rand(ComplexF64, 6) v5 = view(v6, 1:5) @test F\v5 == F\v6[1:5] diff --git a/stdlib/LinearAlgebra/test/cholesky.jl b/stdlib/LinearAlgebra/test/cholesky.jl index 08bacab8cf66e3..1cadf5444b0459 100644 --- a/stdlib/LinearAlgebra/test/cholesky.jl +++ b/stdlib/LinearAlgebra/test/cholesky.jl @@ -18,8 +18,8 @@ function unary_ops_tests(a, ca, tol; n=size(a, 1)) end function factor_recreation_tests(a_U, a_L) - c_U = cholfact(a_U) - c_L = cholfact(a_L) + c_U = cholesky(a_U) + c_L = cholesky(a_L) cl = chol(a_L) ls = c_L.L @test Array(c_U) ≈ Array(c_L) ≈ a_U @@ -55,7 +55,7 @@ end # Test of symmetric pos. def. strided matrix apd = a'*a - @inferred cholfact(apd) + @inferred cholesky(apd) @inferred chol(apd) capd = factorize(apd) r = capd.U @@ -67,7 +67,7 @@ end A = rand(eltya, 2, 3) @test_throws DimensionMismatch chol(A) @test_throws DimensionMismatch LinearAlgebra.chol!(A) - @test_throws DimensionMismatch cholfact(A) + @test_throws DimensionMismatch cholesky(A) @test_throws DimensionMismatch cholfact!(A) end @@ -88,16 +88,16 @@ end @inferred(logdet(capd)) apos = apd[1,1] # test chol(x::Number), needs x>0 - @test all(x -> x ≈ √apos, cholfact(apos).factors) + @test all(x -> x ≈ √apos, cholesky(apos).factors) @test_throws PosDefException chol(-one(eltya)) - # Test cholfact with Symmetric/Hermitian upper/lower + # Test cholesky with Symmetric/Hermitian upper/lower apds = Symmetric(apd) apdsL = Symmetric(apd, :L) apdh = Hermitian(apd) apdhL = Hermitian(apd, :L) if eltya <: Real - capds = cholfact(apds) + capds = cholesky(apds) unary_ops_tests(apds, capds, ε*κ*n) if eltya <: BlasReal capds = cholfact!(copy(apds)) @@ -106,7 +106,7 @@ end ulstring = sprint((t, s) -> show(t, "text/plain", s), capds.UL) @test sprint((t, s) -> show(t, "text/plain", s), capds) == "$(typeof(capds))\nU factor:\n$ulstring" else - capdh = cholfact(apdh) + capdh = cholesky(apdh) unary_ops_tests(apdh, capdh, ε*κ*n) capdh = cholfact!(copy(apdh)) unary_ops_tests(apdh, capdh, ε*κ*n) @@ -129,9 +129,9 @@ end #pivoted upper Cholesky if eltya != BigFloat - cz = cholfact(Hermitian(zeros(eltya,n,n)), Val(true)) + cz = cholesky(Hermitian(zeros(eltya,n,n)), Val(true)) @test_throws LinearAlgebra.RankDeficientException LinearAlgebra.chkfullrank(cz) - cpapd = cholfact(apdh, Val(true)) + cpapd = cholesky(apdh, Val(true)) unary_ops_tests(apdh, cpapd, ε*κ*n) @test rank(cpapd) == n @test all(diff(diag(real(cpapd.factors))).<=0.) # diagonal should be non-increasing @@ -155,18 +155,18 @@ end @test norm(a*(capd\(a'*b)) - b,1)/norm(b,1) <= ε*κ*n # Ad hoc, revisit if eltya != BigFloat && eltyb != BigFloat - lapd = cholfact(apdhL) + lapd = cholesky(apdhL) @test norm(apd * (lapd\b) - b)/norm(b) <= ε*κ*n @test norm(apd * (lapd\b[1:n]) - b[1:n])/norm(b[1:n]) <= ε*κ*n end if eltya != BigFloat && eltyb != BigFloat # Note! Need to implement pivoted Cholesky decomposition in julia - cpapd = cholfact(apdh, Val(true)) + cpapd = cholesky(apdh, Val(true)) @test norm(apd * (cpapd\b) - b)/norm(b) <= ε*κ*n # Ad hoc, revisit @test norm(apd * (cpapd\b[1:n]) - b[1:n])/norm(b[1:n]) <= ε*κ*n - lpapd = cholfact(apdhL, Val(true)) + lpapd = cholesky(apdhL, Val(true)) @test norm(apd * (lpapd\b) - b)/norm(b) <= ε*κ*n # Ad hoc, revisit @test norm(apd * (lpapd\b[1:n]) - b[1:n])/norm(b[1:n]) <= ε*κ*n @@ -176,7 +176,7 @@ end if eltya <: BlasFloat @testset "throw for non positive definite matrix" begin A = eltya[1 2; 2 1]; B = eltya[1, 1] - C = cholfact(A) + C = cholesky(A) @test !isposdef(C) @test !LinearAlgebra.issuccess(C) Cstr = sprint((t, s) -> show(t, "text/plain", s), C) @@ -194,8 +194,8 @@ end A = randn(5,5) end A = convert(Matrix{eltya}, A'A) - @test Matrix(cholfact(A).L) ≈ Matrix(invoke(LinearAlgebra._chol!, Tuple{AbstractMatrix, Type{LowerTriangular}}, copy(A), LowerTriangular)[1]) - @test Matrix(cholfact(A).U) ≈ Matrix(invoke(LinearAlgebra._chol!, Tuple{AbstractMatrix, Type{UpperTriangular}}, copy(A), UpperTriangular)[1]) + @test Matrix(cholesky(A).L) ≈ Matrix(invoke(LinearAlgebra._chol!, Tuple{AbstractMatrix, Type{LowerTriangular}}, copy(A), LowerTriangular)[1]) + @test Matrix(cholesky(A).U) ≈ Matrix(invoke(LinearAlgebra._chol!, Tuple{AbstractMatrix, Type{UpperTriangular}}, copy(A), UpperTriangular)[1]) end end end @@ -219,8 +219,8 @@ end AcA = A'*A BcB = AcA + v*v' BcB = (BcB + BcB')/2 - F = cholfact(Hermitian(AcA, uplo)) - G = cholfact(Hermitian(BcB, uplo)) + F = cholesky(Hermitian(AcA, uplo)) + G = cholesky(Hermitian(BcB, uplo)) @test Base.getproperty(LinearAlgebra.lowrankupdate(F, v), uplo) ≈ Base.getproperty(G, uplo) @test_throws DimensionMismatch LinearAlgebra.lowrankupdate(F, Vector{eltype(v)}(undef,length(v)+1)) @test Base.getproperty(LinearAlgebra.lowrankdowndate(G, v), uplo) ≈ Base.getproperty(F, uplo) @@ -228,7 +228,7 @@ end end end -@testset "issue #13243, unexpected nans in complex cholfact" begin +@testset "issue #13243, unexpected nans in complex cholesky" begin apd = [5.8525753f0 + 0.0f0im -0.79540455f0 + 0.7066077f0im 0.98274714f0 + 1.3824869f0im 2.619998f0 + 1.8532984f0im -1.8306153f0 - 1.2336911f0im 0.32275113f0 + 0.015575029f0im 2.1968813f0 + 1.0640624f0im 0.27894387f0 + 0.97911835f0im 3.0476584f0 + 0.18548489f0im 0.3842994f0 + 0.7050991f0im -0.79540455f0 - 0.7066077f0im 8.313246f0 + 0.0f0im -1.8076122f0 - 0.8882447f0im 0.47806996f0 + 0.48494184f0im 0.5096429f0 - 0.5395974f0im -0.7285097f0 - 0.10360408f0im -1.1760061f0 - 2.7146957f0im -0.4271084f0 + 0.042899966f0im -1.7228563f0 + 2.8335886f0im 1.8942566f0 + 0.6389735f0im 0.98274714f0 - 1.3824869f0im -1.8076122f0 + 0.8882447f0im 9.367975f0 + 0.0f0im -0.1838578f0 + 0.6468568f0im -1.8338387f0 + 0.7064959f0im 0.041852742f0 - 0.6556877f0im 2.5673025f0 + 1.9732997f0im -1.1148382f0 - 0.15693812f0im 2.4704504f0 - 1.0389464f0im 1.0858271f0 - 1.298006f0im @@ -249,7 +249,7 @@ end 0.25336108035924787 + 0.975317836492159im 0.0628393808469436 - 0.1253397353973715im 0.11192755545114 - 0.1603741874112385im 0.8439562576196216 + 1.0850814110398734im -1.0568488936791578 - 0.06025820467086475im 0.12696236014017806 - 0.09853584666755086im] - cholfact(Hermitian(apd, :L), Val(true)) \ b + cholesky(Hermitian(apd, :L), Val(true)) \ b r = factorize(apd).U E = abs.(apd - r'*r) ε = eps(abs(float(one(ComplexF32)))) @@ -263,7 +263,7 @@ end R = randn(5, 5) C = complex.(R, R) for A in (R, C) - @test !LinearAlgebra.issuccess(cholfact(A)) + @test !LinearAlgebra.issuccess(cholesky(A)) @test !LinearAlgebra.issuccess(cholfact!(copy(A))) @test_throws PosDefException chol(A) @test_throws PosDefException LinearAlgebra.chol!(copy(A)) diff --git a/stdlib/SparseArrays/src/linalg.jl b/stdlib/SparseArrays/src/linalg.jl index 1a956b7378683a..36dba2f9c80610 100644 --- a/stdlib/SparseArrays/src/linalg.jl +++ b/stdlib/SparseArrays/src/linalg.jl @@ -990,7 +990,7 @@ function factorize(A::SparseMatrixCSC) end # function factorize(A::Symmetric{Float64,SparseMatrixCSC{Float64,Ti}}) where Ti -# F = cholfact(A) +# F = cholesky(A) # if LinearAlgebra.issuccess(F) # return F # else @@ -999,7 +999,7 @@ end # end # end function factorize(A::LinearAlgebra.RealHermSymComplexHerm{Float64,<:SparseMatrixCSC}) - F = cholfact(A) + F = cholesky(A) if LinearAlgebra.issuccess(F) return F else @@ -1008,7 +1008,7 @@ function factorize(A::LinearAlgebra.RealHermSymComplexHerm{Float64,<:SparseMatri end end -chol(A::SparseMatrixCSC) = error("Use cholfact() instead of chol() for sparse matrices.") +chol(A::SparseMatrixCSC) = error("Use cholesky() instead of chol() for sparse matrices.") eig(A::SparseMatrixCSC) = error("Use IterativeEigensolvers.eigs() instead of eig() for sparse matrices.") function Base.cov(X::SparseMatrixCSC; dims::Int=1, corrected::Bool=true) diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index dadda8ce1790a5..f55f90497fba49 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -1321,7 +1321,7 @@ end if Base.USE_GPL_LIBS a = SparseMatrixCSC(2, 2, [1, 3, 5], [1, 2, 1, 2], [1.0, 0.0, 0.0, 1.0]) @test lu(a)\[2.0, 3.0] ≈ [2.0, 3.0] - @test cholfact(a)\[2.0, 3.0] ≈ [2.0, 3.0] + @test cholesky(a)\[2.0, 3.0] ≈ [2.0, 3.0] end end diff --git a/stdlib/SuiteSparse/src/cholmod.jl b/stdlib/SuiteSparse/src/cholmod.jl index 12eff4884e3b00..92dfa7f66997c7 100644 --- a/stdlib/SuiteSparse/src/cholmod.jl +++ b/stdlib/SuiteSparse/src/cholmod.jl @@ -7,7 +7,7 @@ import Base: (*), convert, copy, eltype, getindex, getproperty, show, size, using LinearAlgebra import LinearAlgebra: (\), - cholfact, cholfact!, det, diag, ishermitian, isposdef, + cholesky, cholfact!, det, diag, ishermitian, isposdef, issuccess, issymmetric, ldlt, ldlt!, logdet using SparseArrays @@ -1385,7 +1385,7 @@ factorization `F`. `A` must be a [`SparseMatrixCSC`](@ref) or a [`Symmetric`](@r [`Hermitian`](@ref) view of a `SparseMatrixCSC`. Note that even if `A` doesn't have the type tag, it must still be symmetric or Hermitian. -See also [`cholfact`](@ref). +See also [`cholesky`](@ref). !!! note This method uses the CHOLMOD library from SuiteSparse, which only supports @@ -1401,7 +1401,7 @@ cholfact!(F::Factor, A::Union{SparseMatrixCSC{T}, shift = 0.0) where {T<:Real} = cholfact!(F, Sparse(A); shift = shift) -function cholfact(A::Sparse; shift::Real=0.0, +function cholesky(A::Sparse; shift::Real=0.0, perm::AbstractVector{SuiteSparse_long}=SuiteSparse_long[]) cm = defaults(common_struct) @@ -1417,14 +1417,14 @@ function cholfact(A::Sparse; shift::Real=0.0, end """ - cholfact(A; shift = 0.0, perm = Int[]) -> CHOLMOD.Factor + cholesky(A; shift = 0.0, perm = Int[]) -> CHOLMOD.Factor Compute the Cholesky factorization of a sparse positive definite matrix `A`. `A` must be a [`SparseMatrixCSC`](@ref) or a [`Symmetric`](@ref)/[`Hermitian`](@ref) view of a `SparseMatrixCSC`. Note that even if `A` doesn't have the type tag, it must still be symmetric or Hermitian. A fill-reducing permutation is used. -`F = cholfact(A)` is most frequently used to solve systems of equations with `F\\b`, +`F = cholesky(A)` is most frequently used to solve systems of equations with `F\\b`, but also the methods [`diag`](@ref), [`det`](@ref), and [`logdet`](@ref) are defined for `F`. You can also extract individual factors from `F`, using `F.L`. @@ -1449,11 +1449,11 @@ it should be a permutation of `1:size(A,1)` giving the ordering to use Many other functions from CHOLMOD are wrapped but not exported from the `Base.SparseArrays.CHOLMOD` module. """ -cholfact(A::Union{SparseMatrixCSC{T}, SparseMatrixCSC{Complex{T}}, +cholesky(A::Union{SparseMatrixCSC{T}, SparseMatrixCSC{Complex{T}}, Symmetric{T,SparseMatrixCSC{T,SuiteSparse_long}}, Hermitian{Complex{T},SparseMatrixCSC{Complex{T},SuiteSparse_long}}, Hermitian{T,SparseMatrixCSC{T,SuiteSparse_long}}}; - kws...) where {T<:Real} = cholfact(Sparse(A); kws...) + kws...) where {T<:Real} = cholesky(Sparse(A); kws...) function ldlt!(F::Factor{Tv}, A::Sparse{Tv}; shift::Real=0.0) where Tv @@ -1712,7 +1712,7 @@ const RealHermSymComplexHermF64SSL = Union{ Hermitian{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}, Hermitian{Complex{Float64},SparseMatrixCSC{Complex{Float64},SuiteSparse_long}}} function \(A::RealHermSymComplexHermF64SSL, B::StridedVecOrMat) - F = cholfact(A) + F = cholesky(A) if issuccess(F) return \(F, B) else @@ -1726,7 +1726,7 @@ function \(A::RealHermSymComplexHermF64SSL, B::StridedVecOrMat) end function \(adjA::Adjoint{<:Any,<:RealHermSymComplexHermF64SSL}, B::StridedVecOrMat) A = adjA.parent - F = cholfact(A) + F = cholesky(A) if issuccess(F) return \(adjoint(F), B) else diff --git a/stdlib/SuiteSparse/src/deprecated.jl b/stdlib/SuiteSparse/src/deprecated.jl index a0aa42f2334052..9396f26ff55eae 100644 --- a/stdlib/SuiteSparse/src/deprecated.jl +++ b/stdlib/SuiteSparse/src/deprecated.jl @@ -87,3 +87,15 @@ end shift = 0.0) where {T<:Real}, ldlt!(F, A; shift=shift)) end + +# deprecate cholfact to cholesky +@eval SuiteSparse.CHOLMOD begin + import LinearAlgebra: cholfact + @deprecate(cholfact(A::Sparse; shift::Real=0.0, perm::AbstractVector{SuiteSparse_long}=SuiteSparse_long[]), cholesky(A; shift=shift, perm=perm)) + @deprecate(cholfact(A::Union{SparseMatrixCSC{T}, SparseMatrixCSC{Complex{T}}, + Symmetric{T,SparseMatrixCSC{T,SuiteSparse_long}}, + Hermitian{Complex{T},SparseMatrixCSC{Complex{T},SuiteSparse_long}}, + Hermitian{T,SparseMatrixCSC{T,SuiteSparse_long}}}; + kws...) where {T<:Real}, + cholesky(A; kws...)) +end diff --git a/stdlib/SuiteSparse/test/cholmod.jl b/stdlib/SuiteSparse/test/cholmod.jl index 53681315f6608e..545d9be2983e36 100644 --- a/stdlib/SuiteSparse/test/cholmod.jl +++ b/stdlib/SuiteSparse/test/cholmod.jl @@ -117,12 +117,12 @@ srand(123) @test size(chmal) == size(A) @test size(chmal, 1) == size(A, 1) - chma = cholfact(A) # LL' form + chma = cholesky(A) # LL' form @test CHOLMOD.isvalid(chma) @test unsafe_load(pointer(chma)).is_ll == 1 # check that it is in fact an LLt @test chma\b ≈ x @test nnz(chma) == 489 - @test nnz(cholfact(A, perm=1:size(A,1))) > nnz(chma) + @test nnz(cholesky(A, perm=1:size(A,1))) > nnz(chma) @test size(chma) == size(A) chmal = CHOLMOD.FactorComponent(chma, :L) @test size(chmal) == size(A) @@ -153,7 +153,7 @@ end 2.249,-1.0,2.279,1.4,-1.0,1.0,-1.0,1.0,1.0,1.0], 0) afiro2 = CHOLMOD.aat(afiro, CHOLMOD.SuiteSparse_long[0:50;], CHOLMOD.SuiteSparse_long(1)) CHOLMOD.change_stype!(afiro2, -1) - chmaf = cholfact(afiro2) + chmaf = cholesky(afiro2) y = afiro'*fill(1., size(afiro,1)) sol = chmaf\(afiro*y) # least squares solution @test CHOLMOD.isvalid(sol) @@ -370,23 +370,23 @@ end end # Factor - @test_throws ArgumentError cholfact(A1) - @test_throws ArgumentError cholfact(A1) - @test_throws ArgumentError cholfact(A1, shift=1.0) + @test_throws ArgumentError cholesky(A1) + @test_throws ArgumentError cholesky(A1) + @test_throws ArgumentError cholesky(A1, shift=1.0) @test_throws ArgumentError ldlt(A1) @test_throws ArgumentError ldlt(A1, shift=1.0) C = A1 + copy(adjoint(A1)) λmaxC = eigmax(Array(C)) b = fill(1., size(A1, 1)) - @test_throws LinearAlgebra.PosDefException cholfact(C - 2λmaxC*I)\b - @test_throws LinearAlgebra.PosDefException cholfact(C, shift=-2λmaxC)\b + @test_throws LinearAlgebra.PosDefException cholesky(C - 2λmaxC*I)\b + @test_throws LinearAlgebra.PosDefException cholesky(C, shift=-2λmaxC)\b @test_throws ArgumentError ldlt(C - C[1,1]*I)\b @test_throws ArgumentError ldlt(C, shift=-real(C[1,1]))\b - @test !isposdef(cholfact(C - 2λmaxC*I)) - @test !isposdef(cholfact(C, shift=-2λmaxC)) + @test !isposdef(cholesky(C - 2λmaxC*I)) + @test !isposdef(cholesky(C, shift=-2λmaxC)) @test !LinearAlgebra.issuccess(ldlt(C - C[1,1]*I)) @test !LinearAlgebra.issuccess(ldlt(C, shift=-real(C[1,1]))) - F = cholfact(A1pd) + F = cholesky(A1pd) tmp = IOBuffer() show(tmp, F) @test tmp.size > 0 @@ -404,7 +404,7 @@ end let # to test supernodal, we must use a larger matrix Ftmp = sprandn(100, 100, 0.1) Ftmp = Ftmp'Ftmp + I - @test logdet(cholfact(Ftmp)) ≈ logdet(Array(Ftmp)) + @test logdet(cholesky(Ftmp)) ≈ logdet(Array(Ftmp)) end @test logdet(ldlt(A1pd)) ≈ logdet(Array(A1pd)) @test isposdef(A1pd) @@ -413,9 +413,9 @@ end if elty <: Real @test CHOLMOD.issymmetric(Sparse(A1pd, 0)) - @test CHOLMOD.Sparse(cholfact(Symmetric(A1pd, :L))) == CHOLMOD.Sparse(cholfact(A1pd)) - F1 = CHOLMOD.Sparse(cholfact(Symmetric(A1pd, :L), shift=2)) - F2 = CHOLMOD.Sparse(cholfact(A1pd, shift=2)) + @test CHOLMOD.Sparse(cholesky(Symmetric(A1pd, :L))) == CHOLMOD.Sparse(cholesky(A1pd)) + F1 = CHOLMOD.Sparse(cholesky(Symmetric(A1pd, :L), shift=2)) + F2 = CHOLMOD.Sparse(cholesky(A1pd, shift=2)) @test F1 == F2 @test CHOLMOD.Sparse(ldlt(Symmetric(A1pd, :L))) == CHOLMOD.Sparse(ldlt(A1pd)) F1 = CHOLMOD.Sparse(ldlt(Symmetric(A1pd, :L), shift=2)) @@ -424,9 +424,9 @@ end else @test !CHOLMOD.issymmetric(Sparse(A1pd, 0)) @test CHOLMOD.ishermitian(Sparse(A1pd, 0)) - @test CHOLMOD.Sparse(cholfact(Hermitian(A1pd, :L))) == CHOLMOD.Sparse(cholfact(A1pd)) - F1 = CHOLMOD.Sparse(cholfact(Hermitian(A1pd, :L), shift=2)) - F2 = CHOLMOD.Sparse(cholfact(A1pd, shift=2)) + @test CHOLMOD.Sparse(cholesky(Hermitian(A1pd, :L))) == CHOLMOD.Sparse(cholesky(A1pd)) + F1 = CHOLMOD.Sparse(cholesky(Hermitian(A1pd, :L), shift=2)) + F2 = CHOLMOD.Sparse(cholesky(A1pd, shift=2)) @test F1 == F2 @test CHOLMOD.Sparse(ldlt(Hermitian(A1pd, :L))) == CHOLMOD.Sparse(ldlt(A1pd)) F1 = CHOLMOD.Sparse(ldlt(Hermitian(A1pd, :L), shift=2)) @@ -435,7 +435,7 @@ end end ### cholfact!/ldlt! - F = cholfact(A1pd) + F = cholesky(A1pd) CHOLMOD.change_factor!(elty, false, false, true, true, F) @test unsafe_load(pointer(F)).is_ll == 0 CHOLMOD.change_factor!(elty, true, false, true, true, F) @@ -444,7 +444,7 @@ end @test size(F, 3) == 1 @test_throws ArgumentError size(F, 0) - F = cholfact(A1pdSparse, shift=2) + F = cholesky(A1pdSparse, shift=2) @test isa(CHOLMOD.Sparse(F), CHOLMOD.Sparse{elty}) @test CHOLMOD.Sparse(cholfact!(copy(F), A1pd, shift=2.0)) ≈ CHOLMOD.Sparse(F) # surprisingly, this can cause small ulp size changes so we cannot test exact equality @@ -504,8 +504,8 @@ end p = [2,3,1] p_inv = [3,1,2] - @testset "cholfact, no permutation" begin - Fs = cholfact(As, perm=[1:3;]) + @testset "cholesky, no permutation" begin + Fs = cholesky(As, perm=[1:3;]) @test Fs.p == [1:3;] @test sparse(Fs.L) ≈ Lf @test sparse(Fs) ≈ As @@ -527,11 +527,11 @@ end @test_throws CHOLMOD.CHOLMODException Fs.DUPt end - @testset "cholfact, with permutation" begin - Fs = cholfact(As, perm=p) + @testset "cholesky, with permutation" begin + Fs = cholesky(As, perm=p) @test Fs.p == p Afp = Af[p,p] - Lfp = cholfact(Afp).L + Lfp = cholesky(Afp).L @test sparse(Fs.L) ≈ Lfp @test sparse(Fs) ≈ As b = rand(3) @@ -617,19 +617,19 @@ end end @testset "Element promotion and type inference" begin - @inferred cholfact(As)\fill(1, size(As, 1)) + @inferred cholesky(As)\fill(1, size(As, 1)) @inferred ldlt(As)\fill(1, size(As, 1)) end end @testset "Issue 11745 - row and column pointers were not sorted in sparse(Factor)" begin A = Float64[10 1 1 1; 1 10 0 0; 1 0 10 0; 1 0 0 10] - @test sparse(cholfact(sparse(A))) ≈ A + @test sparse(cholesky(sparse(A))) ≈ A end GC.gc() @testset "Issue 11747 - Wrong show method defined for FactorComponent" begin - v = cholfact(sparse(Float64[ 10 1 1 1; 1 10 0 0; 1 0 10 0; 1 0 0 10])).L + v = cholesky(sparse(Float64[ 10 1 1 1; 1 10 0 0; 1 0 10 0; 1 0 0 10])).L for s in (sprint(show, MIME("text/plain"), v), sprint(show, v)) @test occursin("method: simplicial", s) @test !occursin("#undef", s) @@ -637,7 +637,7 @@ GC.gc() end @testset "Issue 14076" begin - @test cholfact(sparse([1,2,3,4], [1,2,3,4], Float32[1,4,16,64]))\[1,4,16,64] == fill(1, 4) + @test cholesky(sparse([1,2,3,4], [1,2,3,4], Float32[1,4,16,64]))\[1,4,16,64] == fill(1, 4) end @testset "Issue 14134" begin @@ -650,7 +650,7 @@ end @test_throws ArgumentError size(Anew) @test_throws ArgumentError Anew[1] @test_throws ArgumentError Anew[2,1] - F = cholfact(A) + F = cholesky(A) serialize(b, F) seekstart(b) Fnew = deserialize(b) @@ -669,17 +669,17 @@ end @testset "Further issue with promotion #14894" begin x = fill(1., 5) - @test cholfact(sparse(Float16(1)I, 5, 5))\x == x - @test cholfact(Symmetric(sparse(Float16(1)I, 5, 5)))\x == x - @test cholfact(Hermitian(sparse(Complex{Float16}(1)I, 5, 5)))\x == x - @test_throws MethodError cholfact(sparse(BigFloat(1)I, 5, 5)) - @test_throws MethodError cholfact(Symmetric(sparse(BigFloat(1)I, 5, 5))) - @test_throws MethodError cholfact(Hermitian(sparse(Complex{BigFloat}(1)I, 5, 5))) + @test cholesky(sparse(Float16(1)I, 5, 5))\x == x + @test cholesky(Symmetric(sparse(Float16(1)I, 5, 5)))\x == x + @test cholesky(Hermitian(sparse(Complex{Float16}(1)I, 5, 5)))\x == x + @test_throws MethodError cholesky(sparse(BigFloat(1)I, 5, 5)) + @test_throws MethodError cholesky(Symmetric(sparse(BigFloat(1)I, 5, 5))) + @test_throws MethodError cholesky(Hermitian(sparse(Complex{BigFloat}(1)I, 5, 5))) end @testset "test \\ for Factor and StridedVecOrMat" begin x = rand(5) - A = cholfact(sparse(Diagonal(x.\1))) + A = cholesky(sparse(Diagonal(x.\1))) @test A\view(fill(1.,10),1:2:10) ≈ x @test A\view(Matrix(1.0I, 5, 5), :, :) ≈ Matrix(Diagonal(x)) end @@ -687,7 +687,7 @@ end @testset "Real factorization and complex rhs" begin A = sprandn(5, 5, 0.4) |> t -> t't + I B = complex.(randn(5, 2), randn(5, 2)) - @test cholfact(A)\B ≈ A\B + @test cholesky(A)\B ≈ A\B end @testset "Make sure that ldlt performs an LDLt (Issue #19032)" begin @@ -699,7 +699,7 @@ end s = unsafe_load(pointer(F)) @test s.is_super == 0 @test F\b ≈ fill(1., m+n) - F2 = cholfact(M) + F2 = cholesky(M) @test !LinearAlgebra.issuccess(F2) ldlt!(F2, M) @test LinearAlgebra.issuccess(F2) @@ -708,8 +708,8 @@ end @testset "Test that imaginary parts in Hermitian{T,SparseMatrixCSC{T}} are ignored" begin A = sparse([1,2,3,4,1], [1,2,3,4,2], [complex(2.0,1),2,2,2,1]) - Fs = cholfact(Hermitian(A)) - Fd = cholfact(Hermitian(Array(A))) + Fs = cholesky(Hermitian(A)) + Fd = cholesky(Hermitian(Array(A))) @test sparse(Fs) ≈ Hermitian(A) @test Fs\fill(1., 4) ≈ Fd\fill(1., 4) end @@ -768,8 +768,8 @@ end 1.02371, -0.502384, 1.10686, 0.262229, -1.6935, 0.525239]) AtA = A'*A C0 = [1., 2., 0, 0, 0] - # Test both cholfact and LDLt with and without automatic permutations - for F in (cholfact(AtA), cholfact(AtA, perm=1:5), ldlt(AtA), ldlt(AtA, perm=1:5)) + # Test both cholesky and LDLt with and without automatic permutations + for F in (cholesky(AtA), cholesky(AtA, perm=1:5), ldlt(AtA), ldlt(AtA, perm=1:5)) local F x0 = F\(b = fill(1., 5)) #Test both sparse/dense and vectors/matrices @@ -805,9 +805,9 @@ end @testset "Issue #22335" begin local A, F A = sparse(1.0I, 3, 3) - @test LinearAlgebra.issuccess(cholfact(A)) + @test LinearAlgebra.issuccess(cholesky(A)) A[3, 3] = -1 - F = cholfact(A) + F = cholesky(A) @test !LinearAlgebra.issuccess(F) @test LinearAlgebra.issuccess(ldlt!(F, A)) A[3, 3] = 1