From 6051a03b4e1ea06765604fbd6e71a7dd997b02ca Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Sat, 6 Sep 2025 17:44:38 -0400 Subject: [PATCH 1/4] Add `issymmetrictype` and `ishermitiantype` --- src/symmetric.jl | 31 ++++++++++++++++++++++++++++--- src/tridiag.jl | 2 +- test/symmetric.jl | 22 ++++++++++++++++++++++ 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/symmetric.jl b/src/symmetric.jl index 2cc74763..1d786e8b 100644 --- a/src/symmetric.jl +++ b/src/symmetric.jl @@ -461,9 +461,34 @@ issymmetric(A::Hermitian{<:Real}) = true issymmetric(A::Hermitian{<:Complex}) = isreal(A) issymmetric(A::Symmetric) = true -# check if the symmetry is known from the type -_issymmetric(::Union{SymSymTri, Hermitian{<:Real}}) = true -_issymmetric(::Any) = false +""" + issymmetrictype(T::Type) + +Return whether every instance `x` of the type `T` satisfies `issymmetric(x) == tue`, +that is, the fact that the instance is symmetric is known from its type. + +!!! note + An instance `x::T` may still be symmetric when `issymmetrictype(T)` return `false`. +""" +issymmetrictype(::Type) = false +issymmetrictype(::Type{<:Union{Symmetric,Hermitian{<:Real}}}) = true +issymmetrictype(::Type{<:Real}) = true +issymmetrictype(::Type{<:AbstractFloat}) = false +issymmetrictype(::Type{Complex{T}}) where {T} = issymmetrictype(T) + +""" + ishermitiantype(T::Type) + +Return whether every instance `x` of the type `T` satisfies `ishermitian(x) == tue`, +that is, the fact that the instance is hermitian is known from its type. + +!!! note + An instance `x::T` may still be hermitian when `ishermitiantype(T)` return `false`. +""" +ishermitiantype(::Type) = false +ishermitiantype(::Type{<:Union{Symmetric{<:Real},Hermitian}}) = true +ishermitiantype(::Type{<:Real}) = true +ishermitiantype(::Type{<:AbstractFloat}) = false adjoint(A::Hermitian) = A transpose(A::Symmetric) = A diff --git a/src/tridiag.jl b/src/tridiag.jl index a0e3d821..d7861c4e 100644 --- a/src/tridiag.jl +++ b/src/tridiag.jl @@ -111,7 +111,7 @@ function (::Type{SymTri})(A::AbstractMatrix) where {SymTri <: SymTridiagonal} checksquare(A) du = diag(A, 1) d = diag(A) - if !(_issymmetric(A) || _checksymmetric(d, du, diag(A, -1))) + if !(issymmetrictype(typeof(A)) || _checksymmetric(d, du, diag(A, -1))) throw(ArgumentError("matrix is not symmetric; cannot convert to SymTridiagonal")) end return SymTri(d, du) diff --git a/test/symmetric.jl b/test/symmetric.jl index 707b392d..91f0d37d 100644 --- a/test/symmetric.jl +++ b/test/symmetric.jl @@ -1343,4 +1343,26 @@ end @test_throws msg LinearAlgebra.fillband!(Symmetric(A), 2, 0, 1) end +@testset "issymmetrictype/ishermitiantype" begin + fsym(x) = Val(LinearAlgebra.issymmetrictype(typeof(x))) + @test @inferred(fsym(Symmetric(ones(2,2)))) == Val(true) + @test @inferred(fsym(Symmetric(ones(ComplexF64,2,2)))) == Val(true) + @test @inferred(fsym(Hermitian(ones(2,2)))) == Val(true) + @test @inferred(fsym(Hermitian(ones(ComplexF64,2,2)))) == Val(false) + @test @inferred(fsym(1)) == Val(true) + @test @inferred(fsym(1.0)) == Val(false) + @test @inferred(fsym(complex(1))) == Val(true) + @test @inferred(fsym(complex(1.0))) == Val(false) + + fherm(x) = Val(LinearAlgebra.ishermitiantype(typeof(x))) + @test @inferred(fherm(Symmetric(ones(2,2)))) == Val(true) + @test @inferred(fherm(Symmetric(ones(ComplexF64,2,2)))) == Val(false) + @test @inferred(fherm(Hermitian(ones(2,2)))) == Val(true) + @test @inferred(fherm(Hermitian(ones(ComplexF64,2,2)))) == Val(true) + @test @inferred(fherm(1)) == Val(true) + @test @inferred(fherm(1.0)) == Val(false) + @test @inferred(fherm(complex(1))) == Val(false) + @test @inferred(fherm(complex(1.0))) == Val(false) +end + end # module TestSymmetric From f9417e064a5db34614c06a0ab1155a92791cabc5 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Sun, 7 Sep 2025 18:55:16 +0530 Subject: [PATCH 2/4] Fix leftover `_issymmetric` usage --- src/tridiag.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tridiag.jl b/src/tridiag.jl index d7861c4e..8e12b8a3 100644 --- a/src/tridiag.jl +++ b/src/tridiag.jl @@ -118,7 +118,7 @@ function (::Type{SymTri})(A::AbstractMatrix) where {SymTri <: SymTridiagonal} end _checksymmetric(d, du, dl) = all(((x, y),) -> x == transpose(y), zip(du, dl)) && all(issymmetric, d) -_checksymmetric(A::AbstractMatrix) = _issymmetric(A) || _checksymmetric(diagview(A), diagview(A, 1), diagview(A, -1)) +_checksymmetric(A::AbstractMatrix) = issymmetrictype(typeof(A)) || _checksymmetric(diagview(A), diagview(A, 1), diagview(A, -1)) SymTridiagonal{T,V}(S::SymTridiagonal{T,V}) where {T,V<:AbstractVector{T}} = S SymTridiagonal{T,V}(S::SymTridiagonal) where {T,V<:AbstractVector{T}} = From efc43b4dfc1a6b7315cfe234511957e94bc0fc36 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Mon, 8 Sep 2025 13:35:00 +0530 Subject: [PATCH 3/4] Remove explicit test for helper function --- test/tridiag.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/tridiag.jl b/test/tridiag.jl index 7a4d78b9..520192b3 100644 --- a/test/tridiag.jl +++ b/test/tridiag.jl @@ -1155,10 +1155,6 @@ end @testset "SymTridiagonal from Symmetric" begin S = Symmetric(reshape(1:9, 3, 3)) - @testset "helper functions" begin - @test LinearAlgebra._issymmetric(S) - @test !LinearAlgebra._issymmetric(Array(S)) - end ST = SymTridiagonal(S) @test ST == SymTridiagonal(diag(S), diag(S,1)) S = Symmetric(Tridiagonal(1:3, 1:4, 1:3)) From a5975d8e9c6501cd5b20a6d9d0405a1a4e7082eb Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Wed, 10 Sep 2025 18:46:15 +0530 Subject: [PATCH 4/4] Grammar --- src/symmetric.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/symmetric.jl b/src/symmetric.jl index 1d786e8b..caf6ed28 100644 --- a/src/symmetric.jl +++ b/src/symmetric.jl @@ -468,7 +468,7 @@ Return whether every instance `x` of the type `T` satisfies `issymmetric(x) == t that is, the fact that the instance is symmetric is known from its type. !!! note - An instance `x::T` may still be symmetric when `issymmetrictype(T)` return `false`. + An instance `x::T` may still be symmetric when `issymmetrictype(T)` returns `false`. """ issymmetrictype(::Type) = false issymmetrictype(::Type{<:Union{Symmetric,Hermitian{<:Real}}}) = true @@ -483,7 +483,7 @@ Return whether every instance `x` of the type `T` satisfies `ishermitian(x) == t that is, the fact that the instance is hermitian is known from its type. !!! note - An instance `x::T` may still be hermitian when `ishermitiantype(T)` return `false`. + An instance `x::T` may still be hermitian when `ishermitiantype(T)` returns `false`. """ ishermitiantype(::Type) = false ishermitiantype(::Type{<:Union{Symmetric{<:Real},Hermitian}}) = true