Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ext/MatrixAlgebraKitChainRulesCoreExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/MatrixAlgebraKit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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!
Expand Down
10 changes: 5 additions & 5 deletions src/common/matrixproperties.jl
Original file line number Diff line number Diff line change
@@ -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`:

Expand All @@ -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...)

Expand All @@ -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...) &&
Expand All @@ -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)
Expand All @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions test/amd/eigh.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions test/cuda/eigh.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions test/eigh.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
Expand Down
16 changes: 8 additions & 8 deletions test/lq.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -91,15 +91,15 @@ 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

# 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
Expand Down
60 changes: 30 additions & 30 deletions test/orthnull.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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())
Expand All @@ -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

Expand All @@ -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))
Expand All @@ -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))
Expand All @@ -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

Expand All @@ -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

Expand All @@ -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))
Expand All @@ -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)
Expand All @@ -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))
Expand All @@ -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))
Expand All @@ -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)
Expand All @@ -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

Expand All @@ -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))
Expand All @@ -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))
Expand Down
Loading