From 140d5f6984c2583a7400dfc41513b052f030512e Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Wed, 17 Jan 2024 18:06:39 +0530 Subject: [PATCH 1/8] Reroute symmetric algebraic functions through triangular --- stdlib/LinearAlgebra/src/symmetric.jl | 48 ++++++++++++++++++--------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/stdlib/LinearAlgebra/src/symmetric.jl b/stdlib/LinearAlgebra/src/symmetric.jl index 38035e09b4375..71f0cc440b489 100644 --- a/stdlib/LinearAlgebra/src/symmetric.jl +++ b/stdlib/LinearAlgebra/src/symmetric.jl @@ -272,7 +272,25 @@ end diag(A::Symmetric) = symmetric.(diag(parent(A)), sym_uplo(A.uplo)) diag(A::Hermitian) = hermitian.(diag(parent(A)), sym_uplo(A.uplo)) -isdiag(A::HermOrSym) = isdiag(A.uplo == 'U' ? UpperTriangular(A.data) : LowerTriangular(A.data)) +function applytri(f, A::HermOrSym) + if A.uplo == 'U' + f(UpperTriangular(A.data)) + else + f(LowerTriangular(A.data)) + end +end + +function applytri(f, A::HermOrSym, B::HermOrSym) + if A.uplo == B.uplo == 'U' + f(UpperTriangular(A.data), UpperTriangular(B.data)) + elseif A.uplo == B.uplo == 'L' + f(LowerTriangular(A.data), LowerTriangular(B.data)) + else + throw(ArgumentError("uplo of A and B do not match")) + end +end + +isdiag(A::HermOrSym) = applytri(isdiag, A) # For A<:Union{Symmetric,Hermitian}, similar(A[, neweltype]) should yield a matrix with the same # symmetry type, uplo flag, and underlying storage type as A. The following methods cover these cases. @@ -389,9 +407,9 @@ transpose(A::Hermitian) = Transpose(A) real(A::Symmetric{<:Real}) = A real(A::Hermitian{<:Real}) = A -real(A::Symmetric) = Symmetric(real(A.data), sym_uplo(A.uplo)) -real(A::Hermitian) = Hermitian(real(A.data), sym_uplo(A.uplo)) -imag(A::Symmetric) = Symmetric(imag(A.data), sym_uplo(A.uplo)) +real(A::Symmetric) = Symmetric(applytri(parent ∘ real, A), sym_uplo(A.uplo)) +real(A::Hermitian) = Hermitian(applytri(parent ∘ real, A), sym_uplo(A.uplo)) +imag(A::Symmetric) = Symmetric(applytri(parent ∘ imag, A), sym_uplo(A.uplo)) Base.copy(A::Adjoint{<:Any,<:Symmetric}) = Symmetric(copy(adjoint(A.parent.data)), ifelse(A.parent.uplo == 'U', :L, :U)) @@ -401,8 +419,8 @@ Base.copy(A::Transpose{<:Any,<:Hermitian}) = tr(A::Symmetric) = tr(A.data) # to avoid AbstractMatrix fallback (incl. allocations) tr(A::Hermitian) = real(tr(A.data)) -Base.conj(A::HermOrSym) = typeof(A)(conj(A.data), A.uplo) -Base.conj!(A::HermOrSym) = typeof(A)(conj!(A.data), A.uplo) +Base.conj(A::HermOrSym) = typeof(A)(applytri(parent ∘ conj, A), A.uplo) +Base.conj!(A::HermOrSym) = typeof(A)(applytri(parent ∘ conj!, A), A.uplo) # tril/triu function tril(A::Hermitian, k::Integer=0) @@ -496,15 +514,15 @@ for (T, trans, real) in [(:Symmetric, :transpose, :identity), (:(Hermitian{<:Uni end end -(-)(A::Symmetric) = Symmetric(-A.data, sym_uplo(A.uplo)) -(-)(A::Hermitian) = Hermitian(-A.data, sym_uplo(A.uplo)) +(-)(A::Symmetric) = Symmetric(applytri(parent ∘ -, A), sym_uplo(A.uplo)) +(-)(A::Hermitian) = Hermitian(applytri(parent ∘ -, A), sym_uplo(A.uplo)) ## Addition/subtraction for f ∈ (:+, :-), (Wrapper, conjugation) ∈ ((:Hermitian, :adjoint), (:Symmetric, :transpose)) @eval begin function $f(A::$Wrapper, B::$Wrapper) if A.uplo == B.uplo - return $Wrapper($f(parent(A), parent(B)), sym_uplo(A.uplo)) + return $Wrapper(applytri(parent ∘ $f, A, B), sym_uplo(A.uplo)) elseif A.uplo == 'U' return $Wrapper($f(parent(A), $conjugation(parent(B))), :U) else @@ -555,12 +573,12 @@ function dot(x::AbstractVector, A::RealHermSymComplexHerm, y::AbstractVector) end # Scaling with Number -*(A::Symmetric, x::Number) = Symmetric(A.data*x, sym_uplo(A.uplo)) -*(x::Number, A::Symmetric) = Symmetric(x*A.data, sym_uplo(A.uplo)) -*(A::Hermitian, x::Real) = Hermitian(A.data*x, sym_uplo(A.uplo)) -*(x::Real, A::Hermitian) = Hermitian(x*A.data, sym_uplo(A.uplo)) -/(A::Symmetric, x::Number) = Symmetric(A.data/x, sym_uplo(A.uplo)) -/(A::Hermitian, x::Real) = Hermitian(A.data/x, sym_uplo(A.uplo)) +*(A::Symmetric, x::Number) = Symmetric(applytri(parent ∘ (y -> y * x), A), sym_uplo(A.uplo)) +*(x::Number, A::Symmetric) = Symmetric(applytri(parent ∘ (y -> x * y), A), sym_uplo(A.uplo)) +*(A::Hermitian, x::Real) = Hermitian(applytri(parent ∘ (y -> y * x), A), sym_uplo(A.uplo)) +*(x::Real, A::Hermitian) = Hermitian(applytri(parent ∘ (y -> x * y), A), sym_uplo(A.uplo)) +/(A::Symmetric, x::Number) = Symmetric(applytri(parent ∘ (y -> y/x), A), sym_uplo(A.uplo)) +/(A::Hermitian, x::Real) = Hermitian(applytri(parent ∘ (y -> y/x), A), sym_uplo(A.uplo)) factorize(A::HermOrSym) = _factorize(A) function _factorize(A::HermOrSym{T}; check::Bool=true) where T From d8b6c88061fd847dfaf96571615d2aaa7d2a0e61 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Wed, 17 Jan 2024 19:32:28 +0530 Subject: [PATCH 2/8] Add tests for Complex{BigFloat} --- stdlib/LinearAlgebra/test/symmetric.jl | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/stdlib/LinearAlgebra/test/symmetric.jl b/stdlib/LinearAlgebra/test/symmetric.jl index b3e0b7b560e7a..e0a40b2c8e035 100644 --- a/stdlib/LinearAlgebra/test/symmetric.jl +++ b/stdlib/LinearAlgebra/test/symmetric.jl @@ -470,6 +470,26 @@ end end end +@testset "non-isbits algebra" begin + for ST in (Symmetric, Hermitian), uplo in (:L, :U) + M = Matrix{Complex{BigFloat}}(undef,2,2) + M[1,1] = rand() + M[2,2] = rand() + M[1+(uplo==:L), 1+(uplo==:U)] = rand(ComplexF64) + S = ST(M, uplo) + MS = Matrix(S) + @test real(S) == real(MS) + @test imag(S) == imag(MS) + @test conj(S) == conj(MS) + @test conj!(copy(S)) == conj(MS) + @test -S == -MS + @test S + S == MS + MS + @test S - S == MS - MS + @test S*2 == 2*S == 2*MS + @test S/2 == MS/2 + end +end + # bug identified in PR #52318: dot products of quaternionic Hermitian matrices, # or any number type where conj(a)*conj(b) ≠ conj(a*b): @testset "dot Hermitian quaternion #52318" begin From ef56e1c3d2a844454a15eea2e930c91f1ae14551 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Wed, 24 Jan 2024 13:05:47 +0530 Subject: [PATCH 3/8] Add parentof_applytri to compose with parent --- stdlib/LinearAlgebra/src/symmetric.jl | 29 ++++++++++++++------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/stdlib/LinearAlgebra/src/symmetric.jl b/stdlib/LinearAlgebra/src/symmetric.jl index 71f0cc440b489..96d59bf60eaf5 100644 --- a/stdlib/LinearAlgebra/src/symmetric.jl +++ b/stdlib/LinearAlgebra/src/symmetric.jl @@ -289,6 +289,7 @@ function applytri(f, A::HermOrSym, B::HermOrSym) throw(ArgumentError("uplo of A and B do not match")) end end +parentof_applytri(f, args...) = applytri(parent ∘ f, args...) isdiag(A::HermOrSym) = applytri(isdiag, A) @@ -407,9 +408,9 @@ transpose(A::Hermitian) = Transpose(A) real(A::Symmetric{<:Real}) = A real(A::Hermitian{<:Real}) = A -real(A::Symmetric) = Symmetric(applytri(parent ∘ real, A), sym_uplo(A.uplo)) -real(A::Hermitian) = Hermitian(applytri(parent ∘ real, A), sym_uplo(A.uplo)) -imag(A::Symmetric) = Symmetric(applytri(parent ∘ imag, A), sym_uplo(A.uplo)) +real(A::Symmetric) = Symmetric(parentof_applytri(real, A), sym_uplo(A.uplo)) +real(A::Hermitian) = Hermitian(parentof_applytri(real, A), sym_uplo(A.uplo)) +imag(A::Symmetric) = Symmetric(parentof_applytri(imag, A), sym_uplo(A.uplo)) Base.copy(A::Adjoint{<:Any,<:Symmetric}) = Symmetric(copy(adjoint(A.parent.data)), ifelse(A.parent.uplo == 'U', :L, :U)) @@ -419,8 +420,8 @@ Base.copy(A::Transpose{<:Any,<:Hermitian}) = tr(A::Symmetric) = tr(A.data) # to avoid AbstractMatrix fallback (incl. allocations) tr(A::Hermitian) = real(tr(A.data)) -Base.conj(A::HermOrSym) = typeof(A)(applytri(parent ∘ conj, A), A.uplo) -Base.conj!(A::HermOrSym) = typeof(A)(applytri(parent ∘ conj!, A), A.uplo) +Base.conj(A::HermOrSym) = typeof(A)(parentof_applytri(conj, A), A.uplo) +Base.conj!(A::HermOrSym) = typeof(A)(parentof_applytri(conj!, A), A.uplo) # tril/triu function tril(A::Hermitian, k::Integer=0) @@ -514,15 +515,15 @@ for (T, trans, real) in [(:Symmetric, :transpose, :identity), (:(Hermitian{<:Uni end end -(-)(A::Symmetric) = Symmetric(applytri(parent ∘ -, A), sym_uplo(A.uplo)) -(-)(A::Hermitian) = Hermitian(applytri(parent ∘ -, A), sym_uplo(A.uplo)) +(-)(A::Symmetric) = Symmetric(parentof_applytri(-, A), sym_uplo(A.uplo)) +(-)(A::Hermitian) = Hermitian(parentof_applytri(-, A), sym_uplo(A.uplo)) ## Addition/subtraction for f ∈ (:+, :-), (Wrapper, conjugation) ∈ ((:Hermitian, :adjoint), (:Symmetric, :transpose)) @eval begin function $f(A::$Wrapper, B::$Wrapper) if A.uplo == B.uplo - return $Wrapper(applytri(parent ∘ $f, A, B), sym_uplo(A.uplo)) + return $Wrapper(parentof_applytri($f, A, B), sym_uplo(A.uplo)) elseif A.uplo == 'U' return $Wrapper($f(parent(A), $conjugation(parent(B))), :U) else @@ -573,12 +574,12 @@ function dot(x::AbstractVector, A::RealHermSymComplexHerm, y::AbstractVector) end # Scaling with Number -*(A::Symmetric, x::Number) = Symmetric(applytri(parent ∘ (y -> y * x), A), sym_uplo(A.uplo)) -*(x::Number, A::Symmetric) = Symmetric(applytri(parent ∘ (y -> x * y), A), sym_uplo(A.uplo)) -*(A::Hermitian, x::Real) = Hermitian(applytri(parent ∘ (y -> y * x), A), sym_uplo(A.uplo)) -*(x::Real, A::Hermitian) = Hermitian(applytri(parent ∘ (y -> x * y), A), sym_uplo(A.uplo)) -/(A::Symmetric, x::Number) = Symmetric(applytri(parent ∘ (y -> y/x), A), sym_uplo(A.uplo)) -/(A::Hermitian, x::Real) = Hermitian(applytri(parent ∘ (y -> y/x), A), sym_uplo(A.uplo)) +*(A::Symmetric, x::Number) = Symmetric(parentof_applytri(y -> y * x, A), sym_uplo(A.uplo)) +*(x::Number, A::Symmetric) = Symmetric(parentof_applytri(y -> x * y, A), sym_uplo(A.uplo)) +*(A::Hermitian, x::Real) = Hermitian(parentof_applytri(y -> y * x, A), sym_uplo(A.uplo)) +*(x::Real, A::Hermitian) = Hermitian(parentof_applytri(y -> x * y, A), sym_uplo(A.uplo)) +/(A::Symmetric, x::Number) = Symmetric(parentof_applytri(y -> y/x, A), sym_uplo(A.uplo)) +/(A::Hermitian, x::Real) = Hermitian(parentof_applytri(y -> y/x, A), sym_uplo(A.uplo)) factorize(A::HermOrSym) = _factorize(A) function _factorize(A::HermOrSym{T}; check::Bool=true) where T From b736a9056fb473e823885a3db22fa1e361507cc1 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Mon, 29 Jan 2024 19:56:40 +0530 Subject: [PATCH 4/8] Add/subtract matrices with different uplo --- stdlib/LinearAlgebra/src/symmetric.jl | 12 +++++++----- stdlib/LinearAlgebra/test/symmetric.jl | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/stdlib/LinearAlgebra/src/symmetric.jl b/stdlib/LinearAlgebra/src/symmetric.jl index 96d59bf60eaf5..8fa51ab242f28 100644 --- a/stdlib/LinearAlgebra/src/symmetric.jl +++ b/stdlib/LinearAlgebra/src/symmetric.jl @@ -280,13 +280,15 @@ function applytri(f, A::HermOrSym) end end -function applytri(f, A::HermOrSym, B::HermOrSym) +function applytri(f, A::HermOrSym, B::HermOrSym, adjAf=identity, adjBf=identity) if A.uplo == B.uplo == 'U' f(UpperTriangular(A.data), UpperTriangular(B.data)) elseif A.uplo == B.uplo == 'L' f(LowerTriangular(A.data), LowerTriangular(B.data)) - else - throw(ArgumentError("uplo of A and B do not match")) + elseif A.uplo == 'U' + f(UpperTriangular(A.data), UpperTriangular(adjBf(B.data))) + else # A.uplo == 'L' + f(UpperTriangular(adjAf(A.data)), UpperTriangular(B.data)) end end parentof_applytri(f, args...) = applytri(parent ∘ f, args...) @@ -525,9 +527,9 @@ for f ∈ (:+, :-), (Wrapper, conjugation) ∈ ((:Hermitian, :adjoint), (:Symmet if A.uplo == B.uplo return $Wrapper(parentof_applytri($f, A, B), sym_uplo(A.uplo)) elseif A.uplo == 'U' - return $Wrapper($f(parent(A), $conjugation(parent(B))), :U) + return $Wrapper(parentof_applytri($f, A, B, identity, $conjugation), :U) else - return $Wrapper($f($conjugation(parent(A)), parent(B)), :U) + return $Wrapper(parentof_applytri($f, A, B, $conjugation, identity), :U) end end end diff --git a/stdlib/LinearAlgebra/test/symmetric.jl b/stdlib/LinearAlgebra/test/symmetric.jl index e0a40b2c8e035..72f9f1a7b7342 100644 --- a/stdlib/LinearAlgebra/test/symmetric.jl +++ b/stdlib/LinearAlgebra/test/symmetric.jl @@ -488,6 +488,22 @@ end @test S*2 == 2*S == 2*MS @test S/2 == MS/2 end + @testset "mixed uplo" begin + Mu = Matrix{Complex{BigFloat}}(undef,2,2) + Mu[1,1] = Mu[2,2] = 3 + Mu[1,2] = 2 + 3im + Ml = Matrix{Complex{BigFloat}}(undef,2,2) + Ml[1,1] = Ml[2,2] = 4 + Ml[2,1] = 4 + 5im + for ST in (Symmetric, Hermitian) + Su = ST(Mu, :U) + MSu = Matrix(Su) + Sl = ST(Ml, :L) + MSl = Matrix(Sl) + @test Su + Sl == Sl + Su == MSu + MSl + @test Su - Sl == -(Sl - Su) == MSu - MSl + end + end end # bug identified in PR #52318: dot products of quaternionic Hermitian matrices, From 2c5bd94a4a86c646bf297e84626d4ec0687a9758 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Thu, 1 Feb 2024 23:51:07 +0530 Subject: [PATCH 5/8] Specialize copy and fix conj --- stdlib/LinearAlgebra/src/symmetric.jl | 7 ++++--- stdlib/LinearAlgebra/test/symmetric.jl | 7 +++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/stdlib/LinearAlgebra/src/symmetric.jl b/stdlib/LinearAlgebra/src/symmetric.jl index 8fa51ab242f28..4a4b1ed718cbf 100644 --- a/stdlib/LinearAlgebra/src/symmetric.jl +++ b/stdlib/LinearAlgebra/src/symmetric.jl @@ -335,8 +335,8 @@ Hermitian{T,S}(A::Hermitian) where {T,S<:AbstractMatrix{T}} = Hermitian{T,S}(con AbstractMatrix{T}(A::Hermitian) where {T} = Hermitian(convert(AbstractMatrix{T}, A.data), sym_uplo(A.uplo)) AbstractMatrix{T}(A::Hermitian{T}) where {T} = copy(A) -copy(A::Symmetric{T,S}) where {T,S} = (B = copy(A.data); Symmetric{T,typeof(B)}(B,A.uplo)) -copy(A::Hermitian{T,S}) where {T,S} = (B = copy(A.data); Hermitian{T,typeof(B)}(B,A.uplo)) +copy(A::Symmetric) = (Symmetric(parentof_applytri(copy, B), sym_uplo(A.uplo))) +copy(A::Hermitian) = (Hermitian(parentof_applytri(copy, B), sym_uplo(A.uplo))) function copyto!(dest::Symmetric, src::Symmetric) if src.uplo == dest.uplo @@ -422,7 +422,8 @@ Base.copy(A::Transpose{<:Any,<:Hermitian}) = tr(A::Symmetric) = tr(A.data) # to avoid AbstractMatrix fallback (incl. allocations) tr(A::Hermitian) = real(tr(A.data)) -Base.conj(A::HermOrSym) = typeof(A)(parentof_applytri(conj, A), A.uplo) +Base.conj(A::Symmetric) = Symmetric(parentof_applytri(conj, A), sym_uplo(A.uplo)) +Base.conj(A::Hermitian) = Hermitian(parentof_applytri(conj, A), sym_uplo(A.uplo)) Base.conj!(A::HermOrSym) = typeof(A)(parentof_applytri(conj!, A), A.uplo) # tril/triu diff --git a/stdlib/LinearAlgebra/test/symmetric.jl b/stdlib/LinearAlgebra/test/symmetric.jl index 72f9f1a7b7342..d3b24ccf78b0b 100644 --- a/stdlib/LinearAlgebra/test/symmetric.jl +++ b/stdlib/LinearAlgebra/test/symmetric.jl @@ -968,4 +968,11 @@ end end end +@testset "conj for immutable" begin + S = Symmetric(reshape((1:16)*im, 4, 4)) + @test conj(S) == conj(Array(S)) + H = Hermitian(reshape((1:16)*im, 4, 4)) + @test conj(H) == conj(Array(H)) +end + end # module TestSymmetric From b74a051eac60890f6e26498e3c37d00aecd36d39 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Fri, 2 Feb 2024 12:47:36 +0530 Subject: [PATCH 6/8] Fix typo in variable name --- stdlib/LinearAlgebra/src/symmetric.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/LinearAlgebra/src/symmetric.jl b/stdlib/LinearAlgebra/src/symmetric.jl index 4a4b1ed718cbf..916f905d663c7 100644 --- a/stdlib/LinearAlgebra/src/symmetric.jl +++ b/stdlib/LinearAlgebra/src/symmetric.jl @@ -335,8 +335,8 @@ Hermitian{T,S}(A::Hermitian) where {T,S<:AbstractMatrix{T}} = Hermitian{T,S}(con AbstractMatrix{T}(A::Hermitian) where {T} = Hermitian(convert(AbstractMatrix{T}, A.data), sym_uplo(A.uplo)) AbstractMatrix{T}(A::Hermitian{T}) where {T} = copy(A) -copy(A::Symmetric) = (Symmetric(parentof_applytri(copy, B), sym_uplo(A.uplo))) -copy(A::Hermitian) = (Hermitian(parentof_applytri(copy, B), sym_uplo(A.uplo))) +copy(A::Symmetric) = (Symmetric(parentof_applytri(copy, A), sym_uplo(A.uplo))) +copy(A::Hermitian) = (Hermitian(parentof_applytri(copy, A), sym_uplo(A.uplo))) function copyto!(dest::Symmetric, src::Symmetric) if src.uplo == dest.uplo From 4db5b7093bc36b3d819a7e230caa8f222e811e20 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Thu, 8 Feb 2024 10:46:12 +0530 Subject: [PATCH 7/8] Reduce loop in add/subtract using conjugation function --- stdlib/LinearAlgebra/src/symmetric.jl | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/stdlib/LinearAlgebra/src/symmetric.jl b/stdlib/LinearAlgebra/src/symmetric.jl index 916f905d663c7..6490de4b3ed80 100644 --- a/stdlib/LinearAlgebra/src/symmetric.jl +++ b/stdlib/LinearAlgebra/src/symmetric.jl @@ -269,6 +269,9 @@ end end end +_conjugation(::Symmetric) = transpose +_conjugation(::Hermitian) = adjoint + diag(A::Symmetric) = symmetric.(diag(parent(A)), sym_uplo(A.uplo)) diag(A::Hermitian) = hermitian.(diag(parent(A)), sym_uplo(A.uplo)) @@ -280,15 +283,15 @@ function applytri(f, A::HermOrSym) end end -function applytri(f, A::HermOrSym, B::HermOrSym, adjAf=identity, adjBf=identity) +function applytri(f, A::HermOrSym, B::HermOrSym) if A.uplo == B.uplo == 'U' f(UpperTriangular(A.data), UpperTriangular(B.data)) elseif A.uplo == B.uplo == 'L' f(LowerTriangular(A.data), LowerTriangular(B.data)) elseif A.uplo == 'U' - f(UpperTriangular(A.data), UpperTriangular(adjBf(B.data))) + f(UpperTriangular(A.data), UpperTriangular(_conjugation(B)(B.data))) else # A.uplo == 'L' - f(UpperTriangular(adjAf(A.data)), UpperTriangular(B.data)) + f(UpperTriangular(_conjugation(A)(A.data)), UpperTriangular(B.data)) end end parentof_applytri(f, args...) = applytri(parent ∘ f, args...) @@ -522,17 +525,9 @@ end (-)(A::Hermitian) = Hermitian(parentof_applytri(-, A), sym_uplo(A.uplo)) ## Addition/subtraction -for f ∈ (:+, :-), (Wrapper, conjugation) ∈ ((:Hermitian, :adjoint), (:Symmetric, :transpose)) - @eval begin - function $f(A::$Wrapper, B::$Wrapper) - if A.uplo == B.uplo - return $Wrapper(parentof_applytri($f, A, B), sym_uplo(A.uplo)) - elseif A.uplo == 'U' - return $Wrapper(parentof_applytri($f, A, B, identity, $conjugation), :U) - else - return $Wrapper(parentof_applytri($f, A, B, $conjugation, identity), :U) - end - end +for f ∈ (:+, :-), Wrapper ∈ (:Hermitian, :Symmetric) + @eval function $f(A::$Wrapper, B::$Wrapper) + $Wrapper(parentof_applytri($f, A, B), sym_uplo(A.uplo)) end end From 2d47f214612e352b7f16b2236d01c16c5463e786 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Thu, 8 Feb 2024 23:13:24 +0530 Subject: [PATCH 8/8] Fix uplo in mixed sum --- stdlib/LinearAlgebra/src/symmetric.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/symmetric.jl b/stdlib/LinearAlgebra/src/symmetric.jl index 6490de4b3ed80..b4b5a8825da8c 100644 --- a/stdlib/LinearAlgebra/src/symmetric.jl +++ b/stdlib/LinearAlgebra/src/symmetric.jl @@ -527,7 +527,8 @@ end ## Addition/subtraction for f ∈ (:+, :-), Wrapper ∈ (:Hermitian, :Symmetric) @eval function $f(A::$Wrapper, B::$Wrapper) - $Wrapper(parentof_applytri($f, A, B), sym_uplo(A.uplo)) + uplo = A.uplo == B.uplo ? sym_uplo(A.uplo) : (:U) + $Wrapper(parentof_applytri($f, A, B), uplo) end end