diff --git a/NEWS.md b/NEWS.md index 9f108b43b36e3..d167490a575ef 100644 --- a/NEWS.md +++ b/NEWS.md @@ -103,9 +103,10 @@ Standard library changes * The shape of an `UpperHessenberg` matrix is preserved under certain arithmetic operations, e.g. when multiplying or dividing by an `UpperTriangular` matrix. ([#40039]) * `cis(A)` now supports matrix arguments ([#40194]). * `dot` now supports `UniformScaling` with `AbstractMatrix` ([#40250]). -* `qr[!]` and `lu[!]` now support `PivotingStrategy` values as their optional `pivot` argument: - defaults are `qr(A, NoPivot())` (vs. `qr(A, ColNorm())` for pivoting) and `lu(A, RowMax())` - (vs. `lu(A, NoPivot())` without pivoting); the former `Val{true/false}`-based calls are deprecated. ([#40623]) +* `qr[!]` and `lu[!]` now support `LinearAlgebra.PivotingStrategy` (singleton type) values + as their optional `pivot` argument: defaults are `qr(A, NoPivot())` (vs. + `qr(A, ColumnNorm())` for pivoting) and `lu(A, RowMaximum())` (vs. `lu(A, NoPivot())` + without pivoting); the former `Val{true/false}`-based calls are deprecated. ([#40623]) #### Markdown diff --git a/stdlib/LinearAlgebra/src/LinearAlgebra.jl b/stdlib/LinearAlgebra/src/LinearAlgebra.jl index 325ce081acba9..d5a2a64467f93 100644 --- a/stdlib/LinearAlgebra/src/LinearAlgebra.jl +++ b/stdlib/LinearAlgebra/src/LinearAlgebra.jl @@ -35,7 +35,7 @@ export BunchKaufman, Cholesky, CholeskyPivoted, - ColNorm, + ColumnNorm, Eigen, GeneralizedEigen, GeneralizedSVD, @@ -50,7 +50,7 @@ export Schur, SVD, Hermitian, - RowMax, + RowMaximum, Symmetric, LowerTriangular, UpperTriangular, @@ -169,8 +169,8 @@ struct QRIteration <: Algorithm end abstract type PivotingStrategy end struct NoPivot <: PivotingStrategy end -struct RowMax <: PivotingStrategy end -struct ColNorm <: PivotingStrategy end +struct RowMaximum <: PivotingStrategy end +struct ColumnNorm <: PivotingStrategy end # Check that stride of matrix/vector is 1 # Writing like this to avoid splatting penalty when called with multiple arguments, diff --git a/stdlib/LinearAlgebra/src/dense.jl b/stdlib/LinearAlgebra/src/dense.jl index d5499d8ed68ae..4159525d07679 100644 --- a/stdlib/LinearAlgebra/src/dense.jl +++ b/stdlib/LinearAlgebra/src/dense.jl @@ -1371,7 +1371,7 @@ function factorize(A::StridedMatrix{T}) where T end return lu(A) end - qr(A, ColNorm()) + qr(A, ColumnNorm()) end factorize(A::Adjoint) = adjoint(factorize(parent(A))) factorize(A::Transpose) = transpose(factorize(parent(A))) diff --git a/stdlib/LinearAlgebra/src/factorization.jl b/stdlib/LinearAlgebra/src/factorization.jl index 2f7e81946016a..5ff215a3eb665 100644 --- a/stdlib/LinearAlgebra/src/factorization.jl +++ b/stdlib/LinearAlgebra/src/factorization.jl @@ -16,9 +16,9 @@ size(F::Adjoint{<:Any,<:Factorization}) = reverse(size(parent(F))) size(F::Transpose{<:Any,<:Factorization}) = reverse(size(parent(F))) checkpositivedefinite(info) = info == 0 || throw(PosDefException(info)) -checknonsingular(info, ::RowMax) = info == 0 || throw(SingularException(info)) +checknonsingular(info, ::RowMaximum) = info == 0 || throw(SingularException(info)) checknonsingular(info, ::NoPivot) = info == 0 || throw(ZeroPivotException(info)) -checknonsingular(info) = checknonsingular(info, RowMax()) +checknonsingular(info) = checknonsingular(info, RowMaximum()) """ issuccess(F::Factorization) diff --git a/stdlib/LinearAlgebra/src/generic.jl b/stdlib/LinearAlgebra/src/generic.jl index 0fdb58e262610..c5f21451cb2dd 100644 --- a/stdlib/LinearAlgebra/src/generic.jl +++ b/stdlib/LinearAlgebra/src/generic.jl @@ -1141,7 +1141,7 @@ function (\)(A::AbstractMatrix, B::AbstractVecOrMat) end return lu(A) \ B end - return qr(A, ColNorm()) \ B + return qr(A, ColumnNorm()) \ B end (\)(a::AbstractVector, b::AbstractArray) = pinv(a) * b diff --git a/stdlib/LinearAlgebra/src/lu.jl b/stdlib/LinearAlgebra/src/lu.jl index 59a421225badc..e55508db6b397 100644 --- a/stdlib/LinearAlgebra/src/lu.jl +++ b/stdlib/LinearAlgebra/src/lu.jl @@ -76,8 +76,8 @@ adjoint(F::LU) = Adjoint(F) transpose(F::LU) = Transpose(F) # StridedMatrix -lu!(A::StridedMatrix{<:BlasFloat}; check::Bool = true) = lu!(A, RowMax(); check=check) -function lu!(A::StridedMatrix{T}, ::RowMax; check::Bool = true) where {T<:BlasFloat} +lu!(A::StridedMatrix{<:BlasFloat}; check::Bool = true) = lu!(A, RowMaximum(); check=check) +function lu!(A::StridedMatrix{T}, ::RowMaximum; check::Bool = true) where {T<:BlasFloat} lpt = LAPACK.getrf!(A) check && checknonsingular(lpt[3]) return LU{T,typeof(A)}(lpt[1], lpt[2], lpt[3]) @@ -85,17 +85,17 @@ end function lu!(A::StridedMatrix{<:BlasFloat}, pivot::NoPivot; check::Bool = true) return generic_lufact!(A, pivot; check = check) end -function lu!(A::HermOrSym, pivot::PivotingStrategy = RowMax(); check::Bool = true) +function lu!(A::HermOrSym, pivot::Union{RowMaximum,NoPivot} = RowMaximum(); check::Bool = true) copytri!(A.data, A.uplo, isa(A, Hermitian)) lu!(A.data, pivot; check = check) end # for backward compatibility # TODO: remove towards Julia v2 -@deprecate lu!(A::Union{StridedMatrix,HermOrSym,Tridiagonal}, ::Val{true}; check::Bool = true) lu!(A, RowMax(); check=check) +@deprecate lu!(A::Union{StridedMatrix,HermOrSym,Tridiagonal}, ::Val{true}; check::Bool = true) lu!(A, RowMaximum(); check=check) @deprecate lu!(A::Union{StridedMatrix,HermOrSym,Tridiagonal}, ::Val{false}; check::Bool = true) lu!(A, NoPivot(); check=check) """ - lu!(A, pivot = RowMax(); check = true) -> LU + lu!(A, pivot = RowMaximum(); check = true) -> LU `lu!` is the same as [`lu`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. An [`InexactError`](@ref) @@ -131,18 +131,14 @@ Stacktrace: [...] ``` """ -lu!(A::StridedMatrix, pivot::PivotingStrategy = RowMax(); check::Bool = true) = +lu!(A::StridedMatrix, pivot::Union{RowMaximum,NoPivot} = RowMaximum(); check::Bool = true) = generic_lufact!(A, pivot; check = check) -function generic_lufact!(A::StridedMatrix{T}, pivot::PivotingStrategy = RowMax(); +function generic_lufact!(A::StridedMatrix{T}, pivot::Union{RowMaximum,NoPivot} = RowMaximum(); check::Bool = true) where {T} # Extract values m, n = size(A) minmn = min(m,n) - if pivot !== RowMax() && pivot !== NoPivot() - throw(ArgumentError("only `RowMax()` and `NoPivot()` are supported as `pivot` argument but you supplied `$pivot`")) - end - # Initialize variables info = 0 ipiv = Vector{BlasInt}(undef, minmn) @@ -150,7 +146,7 @@ function generic_lufact!(A::StridedMatrix{T}, pivot::PivotingStrategy = RowMax() for k = 1:minmn # find index max kp = k - if pivot === RowMax() && k < m + if pivot === RowMaximum() && k < m amax = abs(A[k, k]) for i = k+1:m absi = abs(A[i,k]) @@ -211,7 +207,7 @@ end # for all other types we must promote to a type which is stable under division """ - lu(A, pivot = RowMax(); check = true) -> F::LU + lu(A, pivot = RowMaximum(); check = true) -> F::LU Compute the LU factorization of `A`. @@ -278,12 +274,12 @@ julia> l == F.L && u == F.U && p == F.p true ``` """ -function lu(A::AbstractMatrix{T}, pivot::PivotingStrategy = RowMax(); check::Bool = true) where {T} +function lu(A::AbstractMatrix{T}, pivot::Union{RowMaximum,NoPivot} = RowMaximum(); check::Bool = true) where {T} S = lutype(T) lu!(copy_oftype(A, S), pivot; check = check) end # TODO: remove for Julia v2.0 -@deprecate lu(A::AbstractMatrix, ::Val{true}; check::Bool = true) lu(A, RowMax(); check=check) +@deprecate lu(A::AbstractMatrix, ::Val{true}; check::Bool = true) lu(A, RowMaximum(); check=check) @deprecate lu(A::AbstractMatrix, ::Val{false}; check::Bool = true) lu(A, NoPivot(); check=check) @@ -495,14 +491,10 @@ inv(A::LU{<:BlasFloat,<:StridedMatrix}) = inv!(copy(A)) # Tridiagonal # See dgttrf.f -function lu!(A::Tridiagonal{T,V}, pivot::PivotingStrategy = RowMax(); check::Bool = true) where {T,V} +function lu!(A::Tridiagonal{T,V}, pivot::Union{RowMaximum,NoPivot} = RowMaximum(); check::Bool = true) where {T,V} # Extract values n = size(A, 1) - if pivot !== RowMax() && pivot !== NoPivot() - throw(ArgumentError("only `RowMax()` and `NoPivot()` are supported as `pivot` argument but you supplied `$pivot`")) - end - # Initialize variables info = 0 ipiv = Vector{BlasInt}(undef, n) diff --git a/stdlib/LinearAlgebra/src/qr.jl b/stdlib/LinearAlgebra/src/qr.jl index 2e4c43fb3e48f..390c8a5875773 100644 --- a/stdlib/LinearAlgebra/src/qr.jl +++ b/stdlib/LinearAlgebra/src/qr.jl @@ -248,7 +248,7 @@ end # LAPACK version qr!(A::StridedMatrix{<:BlasFloat}, ::NoPivot; blocksize=36) = QRCompactWY(LAPACK.geqrt!(A, min(min(size(A)...), blocksize))...) -qr!(A::StridedMatrix{<:BlasFloat}, ::ColNorm) = QRPivoted(LAPACK.geqp3!(A)...) +qr!(A::StridedMatrix{<:BlasFloat}, ::ColumnNorm) = QRPivoted(LAPACK.geqp3!(A)...) # Generic fallbacks @@ -293,10 +293,10 @@ Stacktrace: ``` """ qr!(A::AbstractMatrix, ::NoPivot) = qrfactUnblocked!(A) -qr!(A::AbstractMatrix, ::ColNorm) = qrfactPivotedUnblocked!(A) +qr!(A::AbstractMatrix, ::ColumnNorm) = qrfactPivotedUnblocked!(A) qr!(A::AbstractMatrix) = qr!(A, NoPivot()) # TODO: Remove in Julia v2.0 -@deprecate qr!(A::AbstractMatrix, ::Val{true}) qr!(A, ColNorm()) +@deprecate qr!(A::AbstractMatrix, ::Val{true}) qr!(A, ColumnNorm()) @deprecate qr!(A::AbstractMatrix, ::Val{false}) qr!(A, NoPivot()) _qreltype(::Type{T}) where T = typeof(zero(T)/sqrt(abs2(one(T)))) @@ -313,7 +313,7 @@ A = Q R The returned object `F` stores the factorization in a packed format: - - if `pivot == ColNorm()` then `F` is a [`QRPivoted`](@ref) object, + - if `pivot == ColumnNorm()` then `F` is a [`QRPivoted`](@ref) object, - otherwise if the element type of `A` is a BLAS type ([`Float32`](@ref), [`Float64`](@ref), `ComplexF32` or `ComplexF64`), then `F` is a [`QRCompactWY`](@ref) object, @@ -387,7 +387,7 @@ function qr(A::AbstractMatrix{T}, arg...; kwargs...) where T end # TODO: remove in Julia v2.0 @deprecate qr(A::AbstractMatrix, ::Val{false}; kwargs...) qr(A, NoPivot(); kwargs...) -@deprecate qr(A::AbstractMatrix, ::Val{true}; kwargs...) qr(A, ColNorm(); kwargs...) +@deprecate qr(A::AbstractMatrix, ::Val{true}; kwargs...) qr(A, ColumnNorm(); kwargs...) qr(x::Number) = qr(fill(x,1,1)) function qr(v::AbstractVector) diff --git a/stdlib/LinearAlgebra/test/diagonal.jl b/stdlib/LinearAlgebra/test/diagonal.jl index 2d60b487342ca..dcd82618c4968 100644 --- a/stdlib/LinearAlgebra/test/diagonal.jl +++ b/stdlib/LinearAlgebra/test/diagonal.jl @@ -565,7 +565,7 @@ end D = Diagonal(randn(5)) Q = qr(randn(5, 5)).Q @test D * Q' == Array(D) * Q' - Q = qr(randn(5, 5), ColNorm()).Q + Q = qr(randn(5, 5), ColumnNorm()).Q @test_throws ArgumentError lmul!(Q, D) end diff --git a/stdlib/LinearAlgebra/test/generic.jl b/stdlib/LinearAlgebra/test/generic.jl index f55eff180b282..0574523027d54 100644 --- a/stdlib/LinearAlgebra/test/generic.jl +++ b/stdlib/LinearAlgebra/test/generic.jl @@ -388,7 +388,7 @@ LinearAlgebra.Transpose(a::ModInt{n}) where {n} = transpose(a) Base.abs(a::ModInt{n}) where {n} = a Base.:<(a::ModInt{n}, b::ModInt{n}) where {n} = a.k < b.k - @test A*(lu(A, RowMax())\b) == b + @test A*(lu(A, RowMaximum())\b) == b end @testset "Issue 18742" begin diff --git a/stdlib/LinearAlgebra/test/lq.jl b/stdlib/LinearAlgebra/test/lq.jl index c4717fa2f2ee4..5161dc9e77047 100644 --- a/stdlib/LinearAlgebra/test/lq.jl +++ b/stdlib/LinearAlgebra/test/lq.jl @@ -40,7 +40,7 @@ rectangularQ(Q::LinearAlgebra.LQPackedQ) = convert(Array, Q) lqa = lq(a) x = lqa\b l,q = lqa.L, lqa.Q - qra = qr(a, ColNorm()) + qra = qr(a, ColumnNorm()) @testset "Basic ops" begin @test size(lqa,1) == size(a,1) @test size(lqa,3) == 1 diff --git a/stdlib/LinearAlgebra/test/qr.jl b/stdlib/LinearAlgebra/test/qr.jl index 69285772d385c..16f828b4f8861 100644 --- a/stdlib/LinearAlgebra/test/qr.jl +++ b/stdlib/LinearAlgebra/test/qr.jl @@ -102,7 +102,7 @@ rectangularQ(Q::LinearAlgebra.AbstractQ) = convert(Array, Q) @test Base.propertynames(qra) == (:R, :Q) end @testset "(Automatic) Fat (pivoted) QR decomposition" begin - @inferred qr(a, ColNorm()) + @inferred qr(a, ColumnNorm()) qrpa = factorize(a[1:n1,:]) q,r = qrpa.Q, qrpa.R @@ -254,7 +254,7 @@ end A = zeros(1, 2) B = zeros(1, 1) @test A \ B == zeros(2, 1) - @test qr(A, ColNorm()) \ B == zeros(2, 1) + @test qr(A, ColumnNorm()) \ B == zeros(2, 1) end @testset "Issue 24107" begin @@ -276,7 +276,7 @@ end @test A \b ≈ ldiv!(c, qr(A ), b) @test b == b0 c0 = copy(c) - @test Ac\c ≈ ldiv!(b, qr(Ac, ColNorm()), c) + @test Ac\c ≈ ldiv!(b, qr(Ac, ColumnNorm()), c) @test c0 == c end @@ -293,7 +293,7 @@ end @testset "det(Q::Union{QRCompactWYQ, QRPackedQ})" begin # 40 is the number larger than the default block size 36 of QRCompactWY - @testset for n in [1:3; 40], m in [1:3; 40], pivot in (NoPivot(), ColNorm()) + @testset for n in [1:3; 40], m in [1:3; 40], pivot in (NoPivot(), ColumnNorm()) @testset "real" begin @testset for k in 0:min(n, m, 5) A = cat(Array(I(k)), randn(n - k, m - k); dims=(1, 2)) diff --git a/stdlib/LinearAlgebra/test/special.jl b/stdlib/LinearAlgebra/test/special.jl index 6632827703859..48cb65e33eb74 100644 --- a/stdlib/LinearAlgebra/test/special.jl +++ b/stdlib/LinearAlgebra/test/special.jl @@ -192,7 +192,7 @@ end a = rand(n,n) atri = typ(a) b = rand(n,n) - qrb = qr(b, ColNorm()) + qrb = qr(b, ColumnNorm()) @test *(atri, adjoint(qrb.Q)) ≈ Matrix(atri) * qrb.Q' @test rmul!(copy(atri), adjoint(qrb.Q)) ≈ Matrix(atri) * qrb.Q' qrb = qr(b, NoPivot()) diff --git a/stdlib/LinearAlgebra/test/uniformscaling.jl b/stdlib/LinearAlgebra/test/uniformscaling.jl index d6542e2185be1..8c69308d06ce8 100644 --- a/stdlib/LinearAlgebra/test/uniformscaling.jl +++ b/stdlib/LinearAlgebra/test/uniformscaling.jl @@ -500,7 +500,7 @@ end @testset "Factorization solutions" begin J = complex(randn(),randn()) * I - qrp = A -> qr(A, ColNorm()) + qrp = A -> qr(A, ColumnNorm()) # thin matrices X = randn(3,2)