From d225bd5abc6b012585aafc5e3dc7fbc5f22b2244 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Tue, 28 Nov 2023 11:09:59 -0500 Subject: [PATCH 1/7] bugfix for dot of Hermitian{noncommutative} --- stdlib/LinearAlgebra/src/symmetric.jl | 2 +- stdlib/LinearAlgebra/test/symmetric.jl | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/symmetric.jl b/stdlib/LinearAlgebra/src/symmetric.jl index 0c19e26e3dd4a..789ad40a9de94 100644 --- a/stdlib/LinearAlgebra/src/symmetric.jl +++ b/stdlib/LinearAlgebra/src/symmetric.jl @@ -453,7 +453,7 @@ function triu(A::Symmetric, k::Integer=0) end end -for (T, trans, real) in [(:Symmetric, :transpose, :identity), (:Hermitian, :adjoint, :real)] +for (T, trans, real) in [(:Symmetric, :transpose, :identity), (:(Hermitian{<:Union{Real,Complex}}), :adjoint, :real)] @eval begin function dot(A::$T, B::$T) n = size(A, 2) diff --git a/stdlib/LinearAlgebra/test/symmetric.jl b/stdlib/LinearAlgebra/test/symmetric.jl index 224b7b31a50df..a40fd5618f21a 100644 --- a/stdlib/LinearAlgebra/test/symmetric.jl +++ b/stdlib/LinearAlgebra/test/symmetric.jl @@ -4,6 +4,9 @@ module TestSymmetric using Test, LinearAlgebra, Random +isdefined(Main, :Quaternions) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "Quaternions.jl")) +using .Main.Quaternions + Random.seed!(1010) @testset "Pauli σ-matrices: $σ" for σ in map(Hermitian, @@ -462,6 +465,14 @@ end 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 + A, B = [Quaternion.(randn(3,3), randn(3, 3), randn(3, 3), randn(3,3)) |> t -> t + t' for i in 1:2] + @test A == Hermitian(A) && B == Hermitian(B) + @test dot(A,B) ≈ dot(Hermitian(A),Hermitian(B)) +end + #Issue #7647: test xsyevr, xheevr, xstevr drivers. @testset "Eigenvalues in interval for $(typeof(Mi7647))" for Mi7647 in (Symmetric(diagm(0 => 1.0:3.0)), From fd5ab773945b700751c9e635136a77819922e28c Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Tue, 28 Nov 2023 15:19:05 -0500 Subject: [PATCH 2/7] define BASE_TEST_PATH --- stdlib/LinearAlgebra/test/symmetric.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stdlib/LinearAlgebra/test/symmetric.jl b/stdlib/LinearAlgebra/test/symmetric.jl index a40fd5618f21a..3e0b2c45257fd 100644 --- a/stdlib/LinearAlgebra/test/symmetric.jl +++ b/stdlib/LinearAlgebra/test/symmetric.jl @@ -4,6 +4,8 @@ module TestSymmetric using Test, LinearAlgebra, Random +const BASE_TEST_PATH = joinpath(Sys.BINDIR, "..", "share", "julia", "test") + isdefined(Main, :Quaternions) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "Quaternions.jl")) using .Main.Quaternions From f600a820b86e571402ee27d141800a59bc0e9091 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Tue, 28 Nov 2023 16:18:15 -0500 Subject: [PATCH 3/7] define real(::Quaternion) --- test/testhelpers/Quaternions.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/testhelpers/Quaternions.jl b/test/testhelpers/Quaternions.jl index 1eddad322ec40..3413dd514f8b6 100644 --- a/test/testhelpers/Quaternions.jl +++ b/test/testhelpers/Quaternions.jl @@ -20,6 +20,7 @@ Base.abs2(q::Quaternion) = q.s*q.s + q.v1*q.v1 + q.v2*q.v2 + q.v3*q.v3 Base.float(z::Quaternion{T}) where T = Quaternion(float(z.s), float(z.v1), float(z.v2), float(z.v3)) Base.abs(q::Quaternion) = sqrt(abs2(q)) Base.real(::Type{Quaternion{T}}) where {T} = T +Base.real(q::Quaternion) = q.s Base.conj(q::Quaternion) = Quaternion(q.s, -q.v1, -q.v2, -q.v3) Base.isfinite(q::Quaternion) = isfinite(q.s) & isfinite(q.v1) & isfinite(q.v2) & isfinite(q.v3) Base.zero(::Type{Quaternion{T}}) where T = Quaternion{T}(zero(T), zero(T), zero(T), zero(T)) From d34725913a9d04e43341a20f5ae13af807f65eba Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Wed, 29 Nov 2023 10:10:48 -0500 Subject: [PATCH 4/7] Update stdlib/LinearAlgebra/test/symmetric.jl Co-authored-by: Daniel Karrasch --- stdlib/LinearAlgebra/test/symmetric.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/test/symmetric.jl b/stdlib/LinearAlgebra/test/symmetric.jl index 3e0b2c45257fd..82236c2a677eb 100644 --- a/stdlib/LinearAlgebra/test/symmetric.jl +++ b/stdlib/LinearAlgebra/test/symmetric.jl @@ -472,7 +472,10 @@ end @testset "dot Hermitian quaternion #52318" begin A, B = [Quaternion.(randn(3,3), randn(3, 3), randn(3, 3), randn(3,3)) |> t -> t + t' for i in 1:2] @test A == Hermitian(A) && B == Hermitian(B) - @test dot(A,B) ≈ dot(Hermitian(A),Hermitian(B)) + @test dot(A, B) ≈ dot(Hermitian(A), Hermitian(B)) + A, B = [Quaternion.(randn(3,3), randn(3, 3), randn(3, 3), randn(3,3)) |> t -> t + transpose(t) for i in 1:2] + @test A == Symmetric(A) && B == Symmetric(B) + @test dot(A, B) ≈ dot(Symmetric(A), Symmetric(B)) end #Issue #7647: test xsyevr, xheevr, xstevr drivers. From 2dc0c536d23696cd6273c00d312fe073752de1a2 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Wed, 29 Nov 2023 12:54:54 -0500 Subject: [PATCH 5/7] Update Quaternions.jl: missing * methods --- test/testhelpers/Quaternions.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/testhelpers/Quaternions.jl b/test/testhelpers/Quaternions.jl index 3413dd514f8b6..81b7a0c2d0121 100644 --- a/test/testhelpers/Quaternions.jl +++ b/test/testhelpers/Quaternions.jl @@ -34,7 +34,9 @@ Base.:(*)(q::Quaternion, w::Quaternion) = Quaternion(q.s*w.s - q.v1*w.v1 - q.v2* q.s*w.v2 - q.v1*w.v3 + q.v2*w.s + q.v3*w.v1, q.s*w.v3 + q.v1*w.v2 - q.v2*w.v1 + q.v3*w.s) Base.:(*)(q::Quaternion, r::Real) = Quaternion(q.s*r, q.v1*r, q.v2*r, q.v3*r) -Base.:(*)(q::Quaternion, b::Bool) = b * q # remove method ambiguity +Base.:(*)(q::Quaternion, r::Bool) = Quaternion(q.s*r, q.v1*r, q.v2*r, q.v3*r) # remove method ambiguity +Base.:(*)(r::Real, q::Quaternion) = q * r +Base.:(*)(r::Bool, q::Quaternion) = q * r # remove method ambiguity Base.:(/)(q::Quaternion, w::Quaternion) = q * conj(w) * (1.0 / abs2(w)) Base.:(\)(q::Quaternion, w::Quaternion) = conj(q) * w * (1.0 / abs2(q)) From 66aeb392fbc0be285f33406dcea934271e2a85ff Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Thu, 30 Nov 2023 21:39:14 -0500 Subject: [PATCH 6/7] generalize type slightly --- stdlib/LinearAlgebra/src/symmetric.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/symmetric.jl b/stdlib/LinearAlgebra/src/symmetric.jl index 789ad40a9de94..a03f87b4cdd53 100644 --- a/stdlib/LinearAlgebra/src/symmetric.jl +++ b/stdlib/LinearAlgebra/src/symmetric.jl @@ -453,7 +453,7 @@ function triu(A::Symmetric, k::Integer=0) end end -for (T, trans, real) in [(:Symmetric, :transpose, :identity), (:(Hermitian{<:Union{Real,Complex}}), :adjoint, :real)] +for (T, trans, real) in [(:Symmetric, :transpose, :identity), (:RealHermSymComplexHerm, :adjoint, :real)] @eval begin function dot(A::$T, B::$T) n = size(A, 2) From 79b5b70d9a9feab9f330dc9fab66a4fec4e10a26 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Thu, 30 Nov 2023 21:42:24 -0500 Subject: [PATCH 7/7] rm method ambiguity --- stdlib/LinearAlgebra/src/symmetric.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/symmetric.jl b/stdlib/LinearAlgebra/src/symmetric.jl index a03f87b4cdd53..789ad40a9de94 100644 --- a/stdlib/LinearAlgebra/src/symmetric.jl +++ b/stdlib/LinearAlgebra/src/symmetric.jl @@ -453,7 +453,7 @@ function triu(A::Symmetric, k::Integer=0) end end -for (T, trans, real) in [(:Symmetric, :transpose, :identity), (:RealHermSymComplexHerm, :adjoint, :real)] +for (T, trans, real) in [(:Symmetric, :transpose, :identity), (:(Hermitian{<:Union{Real,Complex}}), :adjoint, :real)] @eval begin function dot(A::$T, B::$T) n = size(A, 2)