From c53f309326ba28efed3e48752bd118acc8a867b0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Oct 2025 13:12:50 +0000 Subject: [PATCH 1/6] Initial plan From f622982f78cd63b8bc117d459bddacb5dda8f4db Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Oct 2025 13:31:34 +0000 Subject: [PATCH 2/6] Rename isisometry to isisometric throughout codebase Co-authored-by: lkdvos <37111893+lkdvos@users.noreply.github.com> --- ext/MatrixAlgebraKitChainRulesCoreExt.jl | 2 +- src/MatrixAlgebraKit.jl | 2 +- src/common/matrixproperties.jl | 10 ++-- test/amd/eigh.jl | 4 +- test/cuda/eigh.jl | 4 +- test/eigh.jl | 4 +- test/lq.jl | 16 +++---- test/orthnull.jl | 60 ++++++++++++------------ test/polar.jl | 12 ++--- test/projections.jl | 4 +- test/qr.jl | 18 +++---- test/schur.jl | 2 +- test/svd.jl | 10 ++-- 13 files changed, 74 insertions(+), 74 deletions(-) diff --git a/ext/MatrixAlgebraKitChainRulesCoreExt.jl b/ext/MatrixAlgebraKitChainRulesCoreExt.jl index d8664d80..8e6b930a 100644 --- a/ext/MatrixAlgebraKitChainRulesCoreExt.jl +++ b/ext/MatrixAlgebraKitChainRulesCoreExt.jl @@ -14,7 +14,7 @@ MatrixAlgebraKit.iszerotangent(::AbstractZero) = true @non_differentiable MatrixAlgebraKit.select_algorithm(args...) @non_differentiable MatrixAlgebraKit.initialize_output(args...) @non_differentiable MatrixAlgebraKit.check_input(args...) -@non_differentiable MatrixAlgebraKit.isisometry(args...) +@non_differentiable MatrixAlgebraKit.isisometric(args...) @non_differentiable MatrixAlgebraKit.isunitary(args...) function ChainRulesCore.rrule(::typeof(copy_input), f, A) diff --git a/src/MatrixAlgebraKit.jl b/src/MatrixAlgebraKit.jl index bb6434ab..86c5ef9f 100644 --- a/src/MatrixAlgebraKit.jl +++ b/src/MatrixAlgebraKit.jl @@ -9,7 +9,7 @@ using LinearAlgebra: Diagonal, diag, diagind, isdiag using LinearAlgebra: UpperTriangular, LowerTriangular using LinearAlgebra: BlasFloat, BlasReal, BlasComplex, BlasInt -export isisometry, isunitary, ishermitian, isantihermitian +export isisometric, isunitary, ishermitian, isantihermitian export project_hermitian, project_antihermitian, project_isometric export project_hermitian!, project_antihermitian!, project_isometric! diff --git a/src/common/matrixproperties.jl b/src/common/matrixproperties.jl index 61ff73e9..6f3b6e7b 100644 --- a/src/common/matrixproperties.jl +++ b/src/common/matrixproperties.jl @@ -1,5 +1,5 @@ """ - isisometry(A; side=:left, isapprox_kwargs...) -> Bool + isisometric(A; side=:left, isapprox_kwargs...) -> Bool Test whether a linear map is an isometry, where the type of isometry is controlled by `kind`: @@ -12,7 +12,7 @@ New specializations should overload [`is_left_isometry`](@ref) and [`is_right_is See also [`isunitary`](@ref). """ -function isisometry(A; side::Symbol = :left, isapprox_kwargs...) +function isisometric(A; side::Symbol = :left, isapprox_kwargs...) side === :left && return is_left_isometry(A; isapprox_kwargs...) side === :right && return is_right_isometry(A; isapprox_kwargs...) @@ -25,7 +25,7 @@ end Test whether a linear map is unitary, i.e. `A * A' ≈ I ≈ A' * A`. The `isapprox_kwargs` are passed on to `isapprox` to control the tolerances. -See also [`isisometry`](@ref). +See also [`isisometric`](@ref). """ function isunitary(A; isapprox_kwargs...) return is_left_isometry(A; isapprox_kwargs...) && @@ -42,7 +42,7 @@ end Test whether a linear map is a left isometry, i.e. `A' * A ≈ I`. The `isapprox_kwargs` can be used to control the tolerances of the equality. -See also [`isisometry`](@ref) and [`is_right_isometry`](@ref). +See also [`isisometric`](@ref) and [`is_right_isometry`](@ref). """ is_left_isometry function is_left_isometry(A::AbstractMatrix; atol::Real = 0, rtol::Real = defaulttol(A), norm = LinearAlgebra.norm) @@ -58,7 +58,7 @@ end Test whether a linear map is a right isometry, i.e. `A * A' ≈ I`. The `isapprox_kwargs` can be used to control the tolerances of the equality. -See also [`isisometry`](@ref) and [`is_left_isometry`](@ref). +See also [`isisometric`](@ref) and [`is_left_isometry`](@ref). """ is_right_isometry function is_right_isometry(A::AbstractMatrix; atol::Real = 0, rtol::Real = defaulttol(A), norm = LinearAlgebra.norm) diff --git a/test/amd/eigh.jl b/test/amd/eigh.jl index 0e2cb5be..d3cd25f4 100644 --- a/test/amd/eigh.jl +++ b/test/amd/eigh.jl @@ -48,14 +48,14 @@ end D1, V1 = @constinferred eigh_trunc(A; alg, trunc=truncrank(r)) @test length(diagview(D1)) == r - @test isisometry(V1) + @test isisometric(V1) @test A * V1 ≈ V1 * D1 @test LinearAlgebra.opnorm(A - V1 * D1 * V1') ≈ D₀[r + 1] trunc = trunctol(; atol=s * D₀[r + 1]) D2, V2 = @constinferred eigh_trunc(A; alg, trunc) @test length(diagview(D2)) == r - @test isisometry(V2) + @test isisometric(V2) @test A * V2 ≈ V2 * D2 # test for same subspace diff --git a/test/cuda/eigh.jl b/test/cuda/eigh.jl index eece6be3..0a9be80d 100644 --- a/test/cuda/eigh.jl +++ b/test/cuda/eigh.jl @@ -43,14 +43,14 @@ end D1, V1 = @constinferred eigh_trunc(A; alg, trunc=truncrank(r)) @test length(diagview(D1)) == r - @test isisometry(V1) + @test isisometric(V1) @test A * V1 ≈ V1 * D1 @test LinearAlgebra.opnorm(A - V1 * D1 * V1') ≈ D₀[r + 1] trunc = trunctol(; atol = s * D₀[r + 1]) D2, V2 = @constinferred eigh_trunc(A; alg, trunc) @test length(diagview(D2)) == r - @test isisometry(V2) + @test isisometric(V2) @test A * V2 ≈ V2 * D2 # test for same subspace diff --git a/test/eigh.jl b/test/eigh.jl index fa766abb..74f50604 100644 --- a/test/eigh.jl +++ b/test/eigh.jl @@ -52,14 +52,14 @@ end D1, V1 = @constinferred eigh_trunc(A; alg, trunc = truncrank(r)) @test length(diagview(D1)) == r - @test isisometry(V1) + @test isisometric(V1) @test A * V1 ≈ V1 * D1 @test LinearAlgebra.opnorm(A - V1 * D1 * V1') ≈ D₀[r + 1] trunc = trunctol(; atol = s * D₀[r + 1]) D2, V2 = @constinferred eigh_trunc(A; alg, trunc) @test length(diagview(D2)) == r - @test isisometry(V2) + @test isisometric(V2) @test A * V2 ≈ V2 * D2 s = 1 - sqrt(eps(real(T))) diff --git a/test/lq.jl b/test/lq.jl index 5a52b601..2c8dfefe 100644 --- a/test/lq.jl +++ b/test/lq.jl @@ -17,11 +17,11 @@ eltypes = (Float32, Float64, ComplexF32, ComplexF64) @test L isa Matrix{T} && size(L) == (m, minmn) @test Q isa Matrix{T} && size(Q) == (minmn, n) @test L * Q ≈ A - @test isisometry(Q; side = :right) + @test isisometric(Q; side = :right) Nᴴ = @constinferred lq_null(A) @test Nᴴ isa Matrix{T} && size(Nᴴ) == (n - minmn, n) @test maximum(abs, A * Nᴴ') < eps(real(T))^(2 / 3) - @test isisometry(Nᴴ; side = :right) + @test isisometric(Nᴴ; side = :right) Ac = similar(A) L2, Q2 = @constinferred lq_compact!(copy!(Ac, A), (L, Q)) @@ -51,12 +51,12 @@ eltypes = (Float32, Float64, ComplexF32, ComplexF64) # unblocked algorithm lq_compact!(copy!(Ac, A), (L, Q); blocksize = 1) @test L * Q ≈ A - @test isisometry(Q; side = :right) + @test isisometric(Q; side = :right) lq_compact!(copy!(Ac, A), (noL, Q2); blocksize = 1) @test Q == Q2 lq_null!(copy!(Ac, A), Nᴴ; blocksize = 1) @test maximum(abs, A * Nᴴ') < eps(real(T))^(2 / 3) - @test isisometry(Nᴴ; side = :right) + @test isisometric(Nᴴ; side = :right) if m <= n lq_compact!(copy!(Q2, A), (noL, Q2); blocksize = 1) # in-place Q @test Q ≈ Q2 @@ -66,12 +66,12 @@ eltypes = (Float32, Float64, ComplexF32, ComplexF64) end lq_compact!(copy!(Ac, A), (L, Q); blocksize = 8) @test L * Q ≈ A - @test isisometry(Q; side = :right) + @test isisometric(Q; side = :right) lq_compact!(copy!(Ac, A), (noL, Q2); blocksize = 8) @test Q == Q2 lq_null!(copy!(Ac, A), Nᴴ; blocksize = 8) @test maximum(abs, A * Nᴴ') < eps(real(T))^(2 / 3) - @test isisometry(Nᴴ; side = :right) + @test isisometric(Nᴴ; side = :right) @test Nᴴ * Nᴴ' ≈ I qr_alg = LAPACK_HouseholderQR(; blocksize = 1) @@ -91,7 +91,7 @@ eltypes = (Float32, Float64, ComplexF32, ComplexF64) # positive lq_compact!(copy!(Ac, A), (L, Q); positive = true) @test L * Q ≈ A - @test isisometry(Q; side = :right) + @test isisometric(Q; side = :right) @test all(>=(zero(real(T))), real(diag(L))) lq_compact!(copy!(Ac, A), (noL, Q2); positive = true) @test Q == Q2 @@ -99,7 +99,7 @@ eltypes = (Float32, Float64, ComplexF32, ComplexF64) # positive and blocksize 1 lq_compact!(copy!(Ac, A), (L, Q); positive = true, blocksize = 1) @test L * Q ≈ A - @test isisometry(Q; side = :right) + @test isisometric(Q; side = :right) @test all(>=(zero(real(T))), real(diag(L))) lq_compact!(copy!(Ac, A), (noL, Q2); positive = true, blocksize = 1) @test Q == Q2 diff --git a/test/orthnull.jl b/test/orthnull.jl index eac92be3..fc364916 100644 --- a/test/orthnull.jl +++ b/test/orthnull.jl @@ -68,9 +68,9 @@ end @test C isa Matrix{T} && size(C) == (minmn, n) @test N isa Matrix{T} && size(N) == (m, m - minmn) @test V * C ≈ A - @test isisometry(V) + @test isisometric(V) @test LinearAlgebra.norm(A' * N) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometry(N) + @test isisometric(N) @test V * V' + N * N' ≈ I M = LinearMap(A) @@ -85,9 +85,9 @@ end @test C isa Matrix{T} && size(C) == (minmn, n) @test N isa Matrix{T} && size(N) == (m, nullity) @test V * C ≈ A - @test isisometry(V) + @test isisometric(V) @test LinearAlgebra.norm(A' * N) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometry(N) + @test isisometric(N) end for alg_qr in ((; positive = true), (; positive = false), LAPACK_HouseholderQR()) @@ -97,9 +97,9 @@ end @test C isa Matrix{T} && size(C) == (minmn, n) @test N isa Matrix{T} && size(N) == (m, m - minmn) @test V * C ≈ A - @test isisometry(V) + @test isisometric(V) @test LinearAlgebra.norm(A' * N) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometry(N) + @test isisometric(N) @test V * V' + N * N' ≈ I end @@ -110,9 +110,9 @@ end @test C2 === C @test N2 === N @test V2 * C2 ≈ A - @test isisometry(V2) + @test isisometric(V2) @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometry(N2) + @test isisometric(N2) @test V2 * V2' + N2 * N2' ≈ I atol = eps(real(T)) @@ -122,9 +122,9 @@ end @test C2 !== C @test N2 !== C @test V2 * C2 ≈ A - @test isisometry(V2) + @test isisometric(V2) @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometry(N2) + @test isisometric(N2) @test V2 * V2' + N2 * N2' ≈ I rtol = eps(real(T)) @@ -138,9 +138,9 @@ end @test C2 !== C @test N2 !== C @test V2 * C2 ≈ A - @test isisometry(V2) + @test isisometric(V2) @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometry(N2) + @test isisometric(N2) @test V2 * V2' + N2 * N2' ≈ I end @@ -150,12 +150,12 @@ end @test V2 === V @test C2 === C @test V2 * C2 ≈ A - @test isisometry(V2) + @test isisometric(V2) if kind != :polar N2 = @constinferred left_null!(copy!(Ac, A), N; kind = kind) @test N2 === N @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometry(N2) + @test isisometric(N2) @test V2 * V2' + N2 * N2' ≈ I end @@ -178,9 +178,9 @@ end @test C2 !== C @test N2 !== C @test V2 * C2 ≈ A - @test isisometry(V2) + @test isisometric(V2) @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometry(N2) + @test isisometric(N2) @test V2 * V2' + N2 * N2' ≈ I else @test_throws ArgumentError left_orth!(copy!(Ac, A), (V, C); kind, trunc = (; atol)) @@ -204,9 +204,9 @@ end @test Vᴴ isa Matrix{T} && size(Vᴴ) == (minmn, n) @test Nᴴ isa Matrix{T} && size(Nᴴ) == (n - minmn, n) @test C * Vᴴ ≈ A - @test isisometry(Vᴴ; side = :right) + @test isisometric(Vᴴ; side = :right) @test LinearAlgebra.norm(A * adjoint(Nᴴ)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometry(Nᴴ; side = :right) + @test isisometric(Nᴴ; side = :right) @test Vᴴ' * Vᴴ + Nᴴ' * Nᴴ ≈ I M = LinearMap(A) @@ -220,9 +220,9 @@ end @test Vᴴ2 === Vᴴ @test Nᴴ2 === Nᴴ @test C2 * Vᴴ2 ≈ A - @test isisometry(Vᴴ2; side = :right) + @test isisometric(Vᴴ2; side = :right) @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometry(Nᴴ; side = :right) + @test isisometric(Nᴴ; side = :right) @test Vᴴ2' * Vᴴ2 + Nᴴ2' * Nᴴ2 ≈ I atol = eps(real(T)) @@ -232,9 +232,9 @@ end @test Vᴴ2 !== Vᴴ @test Nᴴ2 !== Nᴴ @test C2 * Vᴴ2 ≈ A - @test isisometry(Vᴴ2; side = :right) + @test isisometric(Vᴴ2; side = :right) @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometry(Nᴴ; side = :right) + @test isisometric(Nᴴ; side = :right) @test Vᴴ2' * Vᴴ2 + Nᴴ2' * Nᴴ2 ≈ I rtol = eps(real(T)) @@ -244,9 +244,9 @@ end @test Vᴴ2 !== Vᴴ @test Nᴴ2 !== Nᴴ @test C2 * Vᴴ2 ≈ A - @test isisometry(Vᴴ2; side = :right) + @test isisometric(Vᴴ2; side = :right) @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometry(Nᴴ2; side = :right) + @test isisometric(Nᴴ2; side = :right) @test Vᴴ2' * Vᴴ2 + Nᴴ2' * Nᴴ2 ≈ I for kind in (:lq, :polar, :svd) @@ -255,12 +255,12 @@ end @test C2 === C @test Vᴴ2 === Vᴴ @test C2 * Vᴴ2 ≈ A - @test isisometry(Vᴴ2; side = :right) + @test isisometric(Vᴴ2; side = :right) if kind != :polar Nᴴ2 = @constinferred right_null!(copy!(Ac, A), Nᴴ; kind) @test Nᴴ2 === Nᴴ @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometry(Nᴴ2; side = :right) + @test isisometric(Nᴴ2; side = :right) @test Vᴴ2' * Vᴴ2 + Nᴴ2' * Nᴴ2 ≈ I end @@ -271,9 +271,9 @@ end @test Vᴴ2 !== Vᴴ @test Nᴴ2 !== Nᴴ @test C2 * Vᴴ2 ≈ A - @test isisometry(Vᴴ2; side = :right) + @test isisometric(Vᴴ2; side = :right) @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometry(Nᴴ2; side = :right) + @test isisometric(Nᴴ2; side = :right) @test Vᴴ2' * Vᴴ2 + Nᴴ2' * Nᴴ2 ≈ I C2, Vᴴ2 = @constinferred right_orth!(copy!(Ac, A), (C, Vᴴ); kind, trunc = (; rtol)) @@ -282,9 +282,9 @@ end @test Vᴴ2 !== Vᴴ @test Nᴴ2 !== Nᴴ @test C2 * Vᴴ2 ≈ A - @test isisometry(Vᴴ2; side = :right) + @test isisometric(Vᴴ2; side = :right) @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometry(Nᴴ2; side = :right) + @test isisometric(Nᴴ2; side = :right) @test Vᴴ2' * Vᴴ2 + Nᴴ2' * Nᴴ2 ≈ I else @test_throws ArgumentError right_orth!(copy!(Ac, A), (C, Vᴴ); kind, trunc = (; atol)) diff --git a/test/polar.jl b/test/polar.jl index 9e4ee341..8087149e 100644 --- a/test/polar.jl +++ b/test/polar.jl @@ -22,7 +22,7 @@ using LinearAlgebra: LinearAlgebra, I, isposdef @test W isa Matrix{T} && size(W) == (m, n) @test P isa Matrix{T} && size(P) == (n, n) @test W * P ≈ A - @test isisometry(W) + @test isisometric(W) @test isposdef(P) Ac = similar(A) @@ -30,14 +30,14 @@ using LinearAlgebra: LinearAlgebra, I, isposdef @test W2 === W @test P2 === P @test W * P ≈ A - @test isisometry(W) + @test isisometric(W) @test isposdef(P) noP = similar(P, (0, 0)) W2, P2 = @constinferred left_polar!(copy!(Ac, A), (W, noP), alg) @test P2 === noP @test W2 === W - @test isisometry(W) + @test isisometric(W) P = W' * A # compute P explicitly to verify W correctness @test ishermitian(P; rtol = MatrixAlgebraKit.defaulttol(P)) @test isposdef(project_hermitian!(P)) @@ -59,7 +59,7 @@ end @test Wᴴ isa Matrix{T} && size(Wᴴ) == (m, n) @test P isa Matrix{T} && size(P) == (m, m) @test P * Wᴴ ≈ A - @test isisometry(Wᴴ; side = :right) + @test isisometric(Wᴴ; side = :right) @test isposdef(P) Ac = similar(A) @@ -67,14 +67,14 @@ end @test P2 === P @test Wᴴ2 === Wᴴ @test P * Wᴴ ≈ A - @test isisometry(Wᴴ; side = :right) + @test isisometric(Wᴴ; side = :right) @test isposdef(P) noP = similar(P, (0, 0)) P2, Wᴴ2 = @constinferred right_polar!(copy!(Ac, A), (noP, Wᴴ), alg) @test P2 === noP @test Wᴴ2 === Wᴴ - @test isisometry(Wᴴ; side = :right) + @test isisometric(Wᴴ; side = :right) P = A * Wᴴ' # compute P explicitly to verify W correctness @test ishermitian(P; rtol = MatrixAlgebraKit.defaulttol(P)) @test isposdef(project_hermitian!(P)) diff --git a/test/projections.jl b/test/projections.jl index 5698a702..684b3bac 100644 --- a/test/projections.jl +++ b/test/projections.jl @@ -59,7 +59,7 @@ end @testset "algorithm $alg" for alg in algs A = randn(rng, T, m, n) W = project_isometric(A, alg) - @test isisometry(W) + @test isisometric(W) W2 = project_isometric(W, alg) @test W2 ≈ W # stability of the projection @test W * (W' * A) ≈ A @@ -67,7 +67,7 @@ end Ac = similar(A) W2 = @constinferred project_isometric!(copy!(Ac, A), W, alg) @test W2 === W - @test isisometry(W) + @test isisometric(W) # test that W is closer to A then any other isometry for k in 1:10 diff --git a/test/qr.jl b/test/qr.jl index 39d4a2ac..826c320b 100644 --- a/test/qr.jl +++ b/test/qr.jl @@ -18,9 +18,9 @@ eltypes = (Float32, Float64, ComplexF32, ComplexF64) @test Q * R ≈ A N = @constinferred qr_null(A) @test N isa Matrix{T} && size(N) == (m, m - minmn) - @test isisometry(Q) + @test isisometric(Q) @test maximum(abs, A' * N) < eps(real(T))^(2 / 3) - @test isisometry(N) + @test isisometric(N) Ac = similar(A) Q2, R2 = @constinferred qr_compact!(copy!(Ac, A), (Q, R)) @@ -37,13 +37,13 @@ eltypes = (Float32, Float64, ComplexF32, ComplexF64) # unblocked algorithm qr_compact!(copy!(Ac, A), (Q, R); blocksize = 1) @test Q * R ≈ A - @test isisometry(Q) + @test isisometric(Q) qr_compact!(copy!(Ac, A), (Q2, noR); blocksize = 1) @test Q == Q2 qr_compact!(copy!(Ac, A), (Q2, noR); blocksize = 1) qr_null!(copy!(Ac, A), N; blocksize = 1) @test maximum(abs, A' * N) < eps(real(T))^(2 / 3) - @test isisometry(N) + @test isisometric(N) if n <= m qr_compact!(copy!(Q2, A), (Q2, noR); blocksize = 1) # in-place Q @test Q ≈ Q2 @@ -54,12 +54,12 @@ eltypes = (Float32, Float64, ComplexF32, ComplexF64) # other blocking qr_compact!(copy!(Ac, A), (Q, R); blocksize = 8) @test Q * R ≈ A - @test isisometry(Q) + @test isisometric(Q) qr_compact!(copy!(Ac, A), (Q2, noR); blocksize = 8) @test Q == Q2 qr_null!(copy!(Ac, A), N; blocksize = 8) @test maximum(abs, A' * N) < eps(real(T))^(2 / 3) - @test isisometry(N) + @test isisometric(N) # pivoted qr_compact!(copy!(Ac, A), (Q, R); pivoted = true) @@ -70,21 +70,21 @@ eltypes = (Float32, Float64, ComplexF32, ComplexF64) # positive qr_compact!(copy!(Ac, A), (Q, R); positive = true) @test Q * R ≈ A - @test isisometry(Q) + @test isisometric(Q) @test all(>=(zero(real(T))), real(diag(R))) qr_compact!(copy!(Ac, A), (Q2, noR); positive = true) @test Q == Q2 # positive and blocksize 1 qr_compact!(copy!(Ac, A), (Q, R); positive = true, blocksize = 1) @test Q * R ≈ A - @test isisometry(Q) + @test isisometric(Q) @test all(>=(zero(real(T))), real(diag(R))) qr_compact!(copy!(Ac, A), (Q2, noR); positive = true, blocksize = 1) @test Q == Q2 # positive and pivoted qr_compact!(copy!(Ac, A), (Q, R); positive = true, pivoted = true) @test Q * R ≈ A - @test isisometry(Q) + @test isisometric(Q) if n <= m # the following test tries to find the diagonal element (in order to test positivity) # before the column permutation. This only works if all columns have a diagonal diff --git a/test/schur.jl b/test/schur.jl index 897cf155..e24de579 100644 --- a/test/schur.jl +++ b/test/schur.jl @@ -14,7 +14,7 @@ using LinearAlgebra: I TA, Z, vals = @constinferred schur_full(A; alg) @test eltype(TA) == eltype(Z) == T @test eltype(vals) == Tc - @test isisometry(Z) + @test isisometric(Z) @test A * Z ≈ Z * TA Ac = similar(A) diff --git a/test/svd.jl b/test/svd.jl index 21d34337..a5daad96 100644 --- a/test/svd.jl +++ b/test/svd.jl @@ -3,7 +3,7 @@ using Test using TestExtras using StableRNGs using LinearAlgebra: LinearAlgebra, Diagonal, I, isposdef, norm -using MatrixAlgebraKit: TruncatedAlgorithm, diagview, isisometry +using MatrixAlgebraKit: TruncatedAlgorithm, diagview, isisometric const BLASFloats = (Float32, Float64, ComplexF32, ComplexF64) @@ -38,8 +38,8 @@ const BLASFloats = (Float32, Float64, ComplexF32, ComplexF64) @test S isa Diagonal{real(T)} && size(S) == (minmn, minmn) @test Vᴴ isa Matrix{T} && size(Vᴴ) == (minmn, n) @test U * S * Vᴴ ≈ A - @test isisometry(U) - @test isisometry(Vᴴ; side = :right) + @test isisometric(U) + @test isisometric(Vᴴ; side = :right) @test isposdef(S) Ac = similar(A) @@ -50,8 +50,8 @@ const BLASFloats = (Float32, Float64, ComplexF32, ComplexF64) @test S2 === S @test V2ᴴ === Vᴴ @test U * S * Vᴴ ≈ A - @test isisometry(U) - @test isisometry(Vᴴ; side = :right) + @test isisometric(U) + @test isisometric(Vᴴ; side = :right) @test isposdef(S) Sd = @constinferred svd_vals(A, alg′) From c079d0cf8f2a57f14c2c237b660062fa446a3beb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Oct 2025 14:21:57 +0000 Subject: [PATCH 3/6] Rename is_left_isometry and is_right_isometry to isleftisometric and isrightisometric Co-authored-by: lkdvos <37111893+lkdvos@users.noreply.github.com> --- src/common/matrixproperties.jl | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/common/matrixproperties.jl b/src/common/matrixproperties.jl index 6f3b6e7b..feb0fb63 100644 --- a/src/common/matrixproperties.jl +++ b/src/common/matrixproperties.jl @@ -8,13 +8,13 @@ Test whether a linear map is an isometry, where the type of isometry is controll The `isapprox_kwargs` are passed on to `isapprox` to control the tolerances. -New specializations should overload [`is_left_isometry`](@ref) and [`is_right_isometry`](@ref). +New specializations should overload [`isleftisometric`](@ref) and [`isrightisometric`](@ref). See also [`isunitary`](@ref). """ function isisometric(A; side::Symbol = :left, isapprox_kwargs...) - side === :left && return is_left_isometry(A; isapprox_kwargs...) - side === :right && return is_right_isometry(A; isapprox_kwargs...) + side === :left && return isleftisometric(A; isapprox_kwargs...) + side === :right && return isrightisometric(A; isapprox_kwargs...) throw(ArgumentError(lazy"Invalid isometry side: $side")) end @@ -28,24 +28,24 @@ The `isapprox_kwargs` are passed on to `isapprox` to control the tolerances. See also [`isisometric`](@ref). """ function isunitary(A; isapprox_kwargs...) - return is_left_isometry(A; isapprox_kwargs...) && - is_right_isometry(A; isapprox_kwargs...) + return isleftisometric(A; isapprox_kwargs...) && + isrightisometric(A; isapprox_kwargs...) end function isunitary(A::AbstractMatrix; isapprox_kwargs...) size(A, 1) == size(A, 2) || return false - return is_left_isometry(A; isapprox_kwargs...) + return isleftisometric(A; isapprox_kwargs...) end @doc """ - is_left_isometry(A; isapprox_kwargs...) -> Bool + isleftisometric(A; isapprox_kwargs...) -> Bool Test whether a linear map is a left isometry, i.e. `A' * A ≈ I`. The `isapprox_kwargs` can be used to control the tolerances of the equality. -See also [`isisometric`](@ref) and [`is_right_isometry`](@ref). -""" is_left_isometry +See also [`isisometric`](@ref) and [`isrightisometric`](@ref). +""" isleftisometric -function is_left_isometry(A::AbstractMatrix; atol::Real = 0, rtol::Real = defaulttol(A), norm = LinearAlgebra.norm) +function isleftisometric(A::AbstractMatrix; atol::Real = 0, rtol::Real = defaulttol(A), norm = LinearAlgebra.norm) P = A' * A nP = norm(P) # isapprox would use `rtol * max(norm(P), norm(I))` diagview(P) .-= 1 @@ -53,15 +53,15 @@ function is_left_isometry(A::AbstractMatrix; atol::Real = 0, rtol::Real = defaul end @doc """ - is_right_isometry(A; isapprox_kwargs...) -> Bool + isrightisometric(A; isapprox_kwargs...) -> Bool Test whether a linear map is a right isometry, i.e. `A * A' ≈ I`. The `isapprox_kwargs` can be used to control the tolerances of the equality. -See also [`isisometric`](@ref) and [`is_left_isometry`](@ref). -""" is_right_isometry +See also [`isisometric`](@ref) and [`isleftisometric`](@ref). +""" isrightisometric -function is_right_isometry(A::AbstractMatrix; atol::Real = 0, rtol::Real = defaulttol(A), norm = LinearAlgebra.norm) +function isrightisometric(A::AbstractMatrix; atol::Real = 0, rtol::Real = defaulttol(A), norm = LinearAlgebra.norm) P = A * A' nP = norm(P) # isapprox would use `rtol * max(norm(P), norm(I))` diagview(P) .-= 1 From 2176f58d76cd9e6063c0f543277c87f7040bd9a8 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Thu, 9 Oct 2025 17:38:43 -0400 Subject: [PATCH 4/6] rename `is_left_isometric` and `is_right_isometric` --- src/common/matrixproperties.jl | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/common/matrixproperties.jl b/src/common/matrixproperties.jl index feb0fb63..50c4f348 100644 --- a/src/common/matrixproperties.jl +++ b/src/common/matrixproperties.jl @@ -8,13 +8,14 @@ Test whether a linear map is an isometry, where the type of isometry is controll The `isapprox_kwargs` are passed on to `isapprox` to control the tolerances. -New specializations should overload [`isleftisometric`](@ref) and [`isrightisometric`](@ref). +New specializations should overload [`MatrixAlgebraKit.is_left_isometric`](@ref) and +[`MatrixAlgebraKit.is_right_isometric`](@ref). See also [`isunitary`](@ref). """ function isisometric(A; side::Symbol = :left, isapprox_kwargs...) - side === :left && return isleftisometric(A; isapprox_kwargs...) - side === :right && return isrightisometric(A; isapprox_kwargs...) + side === :left && return is_left_isometric(A; isapprox_kwargs...) + side === :right && return is_right_isometric(A; isapprox_kwargs...) throw(ArgumentError(lazy"Invalid isometry side: $side")) end @@ -28,24 +29,24 @@ The `isapprox_kwargs` are passed on to `isapprox` to control the tolerances. See also [`isisometric`](@ref). """ function isunitary(A; isapprox_kwargs...) - return isleftisometric(A; isapprox_kwargs...) && - isrightisometric(A; isapprox_kwargs...) + return is_left_isometric(A; isapprox_kwargs...) && + is_right_isometric(A; isapprox_kwargs...) end function isunitary(A::AbstractMatrix; isapprox_kwargs...) size(A, 1) == size(A, 2) || return false - return isleftisometric(A; isapprox_kwargs...) + return is_left_isometric(A; isapprox_kwargs...) end @doc """ - isleftisometric(A; isapprox_kwargs...) -> Bool + is_left_isometric(A; isapprox_kwargs...) -> Bool -Test whether a linear map is a left isometry, i.e. `A' * A ≈ I`. +Test whether a linear map is a (left) isometry, i.e. `A' * A ≈ I`. The `isapprox_kwargs` can be used to control the tolerances of the equality. -See also [`isisometric`](@ref) and [`isrightisometric`](@ref). -""" isleftisometric +See also [`isisometric`](@ref) and [`MatrixAlgebraKit.is_right_isometric`](@ref). +""" is_left_isometric -function isleftisometric(A::AbstractMatrix; atol::Real = 0, rtol::Real = defaulttol(A), norm = LinearAlgebra.norm) +function is_left_isometric(A::AbstractMatrix; atol::Real = 0, rtol::Real = defaulttol(A), norm = LinearAlgebra.norm) P = A' * A nP = norm(P) # isapprox would use `rtol * max(norm(P), norm(I))` diagview(P) .-= 1 @@ -53,15 +54,15 @@ function isleftisometric(A::AbstractMatrix; atol::Real = 0, rtol::Real = default end @doc """ - isrightisometric(A; isapprox_kwargs...) -> Bool + is_right_isometric(A; isapprox_kwargs...) -> Bool -Test whether a linear map is a right isometry, i.e. `A * A' ≈ I`. +Test whether a linear map is a (right) isometry, i.e. `A * A' ≈ I`. The `isapprox_kwargs` can be used to control the tolerances of the equality. -See also [`isisometric`](@ref) and [`isleftisometric`](@ref). -""" isrightisometric +See also [`isisometric`](@ref) and [`MatrixAlgebraKit.is_left_isometric`](@ref). +""" is_right_isometric -function isrightisometric(A::AbstractMatrix; atol::Real = 0, rtol::Real = defaulttol(A), norm = LinearAlgebra.norm) +function is_right_isometric(A::AbstractMatrix; atol::Real = 0, rtol::Real = defaulttol(A), norm = LinearAlgebra.norm) P = A * A' nP = norm(P) # isapprox would use `rtol * max(norm(P), norm(I))` diagview(P) .-= 1 From 1e36ef1c52d8eefd3110c88ef2c7ba76bb6dc54b Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Thu, 9 Oct 2025 17:38:47 -0400 Subject: [PATCH 5/6] mark as public --- src/MatrixAlgebraKit.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/MatrixAlgebraKit.jl b/src/MatrixAlgebraKit.jl index 86c5ef9f..5211476f 100644 --- a/src/MatrixAlgebraKit.jl +++ b/src/MatrixAlgebraKit.jl @@ -65,6 +65,7 @@ export notrunc, truncrank, trunctol, truncerror, truncfilter :svd_pullback!, :svd_trunc_pullback! ) ) + eval(Expr(:public, :is_left_isometric, :is_right_isometric)) end include("common/defaults.jl") From dc17ad718280cf40d20963cb6cc82a13710bd497 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Thu, 9 Oct 2025 19:29:55 -0400 Subject: [PATCH 6/6] refactor is_right_isometric --- src/common/matrixproperties.jl | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/common/matrixproperties.jl b/src/common/matrixproperties.jl index 50c4f348..224a16cd 100644 --- a/src/common/matrixproperties.jl +++ b/src/common/matrixproperties.jl @@ -61,13 +61,7 @@ The `isapprox_kwargs` can be used to control the tolerances of the equality. See also [`isisometric`](@ref) and [`MatrixAlgebraKit.is_left_isometric`](@ref). """ is_right_isometric - -function is_right_isometric(A::AbstractMatrix; atol::Real = 0, rtol::Real = defaulttol(A), norm = LinearAlgebra.norm) - P = A * A' - nP = norm(P) # isapprox would use `rtol * max(norm(P), norm(I))` - diagview(P) .-= 1 - return norm(P) <= max(atol, rtol * nP) # assume that the norm of I is `sqrt(n)` -end +is_right_isometric(A; kwargs...) = is_left_isometric(A'; kwargs...) """ ishermitian(A; isapprox_kwargs...)