From 68b985d4a88042f2693100a8b47a65ca3922cca7 Mon Sep 17 00:00:00 2001 From: hyrodium Date: Fri, 9 Dec 2022 23:31:47 +0900 Subject: [PATCH 01/13] add support for RealDot --- Project.toml | 1 + src/Quaternion.jl | 3 +++ src/Quaternions.jl | 1 + 3 files changed, 5 insertions(+) diff --git a/Project.toml b/Project.toml index 8e9dfbf..29fb527 100644 --- a/Project.toml +++ b/Project.toml @@ -5,6 +5,7 @@ version = "0.7.0" [deps] LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +RealDot = "c1ae055f-0cd5-4b69-90a6-9a35b1a98df9" [compat] Aqua = "0.5" diff --git a/src/Quaternion.jl b/src/Quaternion.jl index 7ce5c45..56fbd60 100644 --- a/src/Quaternion.jl +++ b/src/Quaternion.jl @@ -386,3 +386,6 @@ LinearAlgebra.lyap(a::Quaternion, c::Quaternion) = lyap(promote(a, c)...) # if a commutes with c, use a simpler expression LinearAlgebra.lyap(a::Real, c::Quaternion) = c / -2a LinearAlgebra.lyap(a::Quaternion, c::Real) = c / -2real(a) + +## RealDot +@inline RealDot.realdot(p::Quaternion, q::Quaternion) = muladd(p.s, q.s, dot(imag_part(p), imag_part(q))) diff --git a/src/Quaternions.jl b/src/Quaternions.jl index ae64e71..8386b51 100644 --- a/src/Quaternions.jl +++ b/src/Quaternions.jl @@ -2,6 +2,7 @@ module Quaternions using Random using LinearAlgebra +using RealDot include("Quaternion.jl") From 59464419804c8feeafd69c326f839f267584aff9 Mon Sep 17 00:00:00 2001 From: hyrodium Date: Fri, 9 Dec 2022 23:38:47 +0900 Subject: [PATCH 02/13] add tests for realdot --- test/Quaternion.jl | 9 +++++++++ test/runtests.jl | 1 + 2 files changed, 10 insertions(+) diff --git a/test/Quaternion.jl b/test/Quaternion.jl index cfd32ca..b9d27d9 100644 --- a/test/Quaternion.jl +++ b/test/Quaternion.jl @@ -571,4 +571,13 @@ end @test_throws DivideError lyap(null, null) end end + + @testset "RealDot with $T" for T in (Float32, Float64) + for _ in 1:10 + q1 = randn(Quaternion{T}) + q2 = randn(Quaternion{T}) + @test real(dot(q1,q2)) ≈ realdot(q1,q2) + @test realdot(q1,q2) isa T + end + end end diff --git a/test/runtests.jl b/test/runtests.jl index feb2b15..4777001 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,6 +1,7 @@ using Test using Quaternions using Aqua +using RealDot Aqua.test_all(Quaternions) From 8269646c3979bdf1f947d9e84a902d3eb9d68283 Mon Sep 17 00:00:00 2001 From: hyrodium Date: Fri, 9 Dec 2022 23:39:06 +0900 Subject: [PATCH 03/13] add compat table for RealDot --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index 29fb527..c5322ec 100644 --- a/Project.toml +++ b/Project.toml @@ -9,6 +9,7 @@ RealDot = "c1ae055f-0cd5-4b69-90a6-9a35b1a98df9" [compat] Aqua = "0.5" +RealDot = "0.1" julia = "1" [extras] From 3906c6e50528f8f6f27d5977e9688990df60ba12 Mon Sep 17 00:00:00 2001 From: Yuto Horikawa Date: Sun, 11 Dec 2022 00:45:27 +0900 Subject: [PATCH 04/13] Add `@inferred` in test for `realdot` Co-authored-by: Seth Axen --- test/Quaternion.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Quaternion.jl b/test/Quaternion.jl index b9d27d9..e62217b 100644 --- a/test/Quaternion.jl +++ b/test/Quaternion.jl @@ -576,7 +576,7 @@ end for _ in 1:10 q1 = randn(Quaternion{T}) q2 = randn(Quaternion{T}) - @test real(dot(q1,q2)) ≈ realdot(q1,q2) + @test real(dot(q1,q2)) ≈ @inferred(realdot(q1,q2)) @test realdot(q1,q2) isa T end end From 5c822a5a7ce32c2faed8d19da7b53c705cbfe307 Mon Sep 17 00:00:00 2001 From: hyrodium Date: Sun, 11 Dec 2022 01:05:25 +0900 Subject: [PATCH 05/13] use realdot in slerp --- src/Quaternion.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Quaternion.jl b/src/Quaternion.jl index 56fbd60..5961694 100644 --- a/src/Quaternion.jl +++ b/src/Quaternion.jl @@ -321,7 +321,7 @@ true iszero(qb0) && throw(DomainError(qb0, "The input quaternion must be non-zero.")) qa = qa0 / abs(qa0) qb = qb0 / abs(qb0) - coshalftheta = qa.s * qb.s + qa.v1 * qb.v1 + qa.v2 * qb.v2 + qa.v3 * qb.v3 + coshalftheta = realdot(qa, qb) if coshalftheta < 0 qb = -qb From ba79d095db1d451a9ee43b5d49b21688c1c77363 Mon Sep 17 00:00:00 2001 From: hyrodium Date: Thu, 15 Dec 2022 11:48:48 +0900 Subject: [PATCH 06/13] =?UTF-8?q?replace=20=E2=89=88=20with=20=3D=3D=20in?= =?UTF-8?q?=20realdot=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/Quaternion.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Quaternion.jl b/test/Quaternion.jl index e62217b..0e3b19e 100644 --- a/test/Quaternion.jl +++ b/test/Quaternion.jl @@ -576,7 +576,7 @@ end for _ in 1:10 q1 = randn(Quaternion{T}) q2 = randn(Quaternion{T}) - @test real(dot(q1,q2)) ≈ @inferred(realdot(q1,q2)) + @test real(dot(q1,q2)) == @inferred(realdot(q1,q2)) @test realdot(q1,q2) isa T end end From 483510d82e3c61ae7c6bf0cc7e3bcc8ae0d4b50b Mon Sep 17 00:00:00 2001 From: hyrodium Date: Thu, 15 Dec 2022 11:49:32 +0900 Subject: [PATCH 07/13] remove muladd in realdot definition --- src/Quaternion.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Quaternion.jl b/src/Quaternion.jl index 5961694..980e431 100644 --- a/src/Quaternion.jl +++ b/src/Quaternion.jl @@ -388,4 +388,4 @@ LinearAlgebra.lyap(a::Real, c::Quaternion) = c / -2a LinearAlgebra.lyap(a::Quaternion, c::Real) = c / -2real(a) ## RealDot -@inline RealDot.realdot(p::Quaternion, q::Quaternion) = muladd(p.s, q.s, dot(imag_part(p), imag_part(q))) +@inline RealDot.realdot(p::Quaternion, q::Quaternion) = (p.s * q.s + p.v2 * q.v2) + (p.v1 * q.v1 + p.v3 * q.v3) From 97aaabc7b4d7a55b5866f45deb6b07cf8a59c5f4 Mon Sep 17 00:00:00 2001 From: Yuto Horikawa Date: Thu, 15 Dec 2022 19:53:43 +0900 Subject: [PATCH 08/13] Add suggested comment Co-authored-by: Seth Axen --- src/Quaternion.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Quaternion.jl b/src/Quaternion.jl index 980e431..1ef8529 100644 --- a/src/Quaternion.jl +++ b/src/Quaternion.jl @@ -388,4 +388,5 @@ LinearAlgebra.lyap(a::Real, c::Quaternion) = c / -2a LinearAlgebra.lyap(a::Quaternion, c::Real) = c / -2real(a) ## RealDot +# ordering chosen so that real(p'q) == real(q'p) == realdot(p, q) == realdot(q, p), i.e. exact equality @inline RealDot.realdot(p::Quaternion, q::Quaternion) = (p.s * q.s + p.v2 * q.v2) + (p.v1 * q.v1 + p.v3 * q.v3) From 6e28c7cd7f716ada13c89b96047f882a43a59dd6 Mon Sep 17 00:00:00 2001 From: Yuto Horikawa Date: Thu, 15 Dec 2022 19:54:08 +0900 Subject: [PATCH 09/13] Use explicit RealDot.realdot Co-authored-by: Seth Axen --- src/Quaternion.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Quaternion.jl b/src/Quaternion.jl index 1ef8529..b63596f 100644 --- a/src/Quaternion.jl +++ b/src/Quaternion.jl @@ -321,7 +321,7 @@ true iszero(qb0) && throw(DomainError(qb0, "The input quaternion must be non-zero.")) qa = qa0 / abs(qa0) qb = qb0 / abs(qb0) - coshalftheta = realdot(qa, qb) + coshalftheta = RealDot.realdot(qa, qb) if coshalftheta < 0 qb = -qb From 16904fdbe90aef33cffe413bffa28362bccc6be8 Mon Sep 17 00:00:00 2001 From: hyrodium Date: Thu, 15 Dec 2022 19:57:12 +0900 Subject: [PATCH 10/13] use RealDot.realdot in abs2 --- src/Quaternion.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Quaternion.jl b/src/Quaternion.jl index b63596f..6e33462 100644 --- a/src/Quaternion.jl +++ b/src/Quaternion.jl @@ -139,7 +139,7 @@ Base.conj(q::Quaternion) = Quaternion(q.s, -q.v1, -q.v2, -q.v3) Base.abs(q::Quaternion) = sqrt(abs2(q)) Base.float(q::Quaternion{T}) where T = convert(Quaternion{float(T)}, q) abs_imag(q::Quaternion) = sqrt(q.v2 * q.v2 + (q.v1 * q.v1 + q.v3 * q.v3)) # ordered to match abs2 -Base.abs2(q::Quaternion) = (q.s * q.s + q.v2 * q.v2) + (q.v1 * q.v1 + q.v3 * q.v3) +Base.abs2(q::Quaternion) = RealDot.realdot(q,q) Base.inv(q::Quaternion) = conj(q) / abs2(q) Base.isreal(q::Quaternion) = iszero(q.v1) & iszero(q.v2) & iszero(q.v3) From 23ef4124174e0162cc50147c55eb5f50556fcf8a Mon Sep 17 00:00:00 2001 From: hyrodium Date: Thu, 15 Dec 2022 20:04:54 +0900 Subject: [PATCH 11/13] add commutative law test for realdot --- test/Quaternion.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Quaternion.jl b/test/Quaternion.jl index 0e3b19e..b039ef3 100644 --- a/test/Quaternion.jl +++ b/test/Quaternion.jl @@ -577,6 +577,7 @@ end q1 = randn(Quaternion{T}) q2 = randn(Quaternion{T}) @test real(dot(q1,q2)) == @inferred(realdot(q1,q2)) + @test realdot(q1,q2) == realdot(q2,q1) @test realdot(q1,q2) isa T end end From 204e32079a8512db0d022a0f4b5706cc08df898e Mon Sep 17 00:00:00 2001 From: hyrodium Date: Thu, 15 Dec 2022 22:39:11 +0900 Subject: [PATCH 12/13] =?UTF-8?q?add=20commutative=20law=20test=20for=20re?= =?UTF-8?q?al=E2=88=98dot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/Quaternion.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/Quaternion.jl b/test/Quaternion.jl index b039ef3..fecefac 100644 --- a/test/Quaternion.jl +++ b/test/Quaternion.jl @@ -576,8 +576,13 @@ end for _ in 1:10 q1 = randn(Quaternion{T}) q2 = randn(Quaternion{T}) + # Check real∘dot is equal to realdot. @test real(dot(q1,q2)) == @inferred(realdot(q1,q2)) + # Check realdot is commutative. @test realdot(q1,q2) == realdot(q2,q1) + # Check real∘dot is also commutative just in case. + @test real(dot(q1,q2)) == real(dot(q2,q1)) + # Check the return type of realdot is correct. @test realdot(q1,q2) isa T end end From 1e3e17cbe84ff5dafea716822bedf6e565a637ea Mon Sep 17 00:00:00 2001 From: hyrodium Date: Fri, 16 Dec 2022 00:41:03 +0900 Subject: [PATCH 13/13] bump version to v0.7.3 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index fcd5806..e325906 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "Quaternions" uuid = "94ee1d12-ae83-5a48-8b1c-48b8ff168ae0" -version = "0.7.2" +version = "0.7.3" [deps] LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"