From 24d38dd2ecfccd28aef39cfb747196997f996e77 Mon Sep 17 00:00:00 2001 From: Yuto Horikawa Date: Wed, 20 Sep 2023 21:36:34 +0900 Subject: [PATCH 01/12] rename logexp to elementary_functions --- src/Rotations.jl | 2 +- src/{logexp.jl => elementary_functions.jl} | 0 test/{logexp.jl => elementary_functions.jl} | 0 test/runtests.jl | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) rename src/{logexp.jl => elementary_functions.jl} (100%) rename test/{logexp.jl => elementary_functions.jl} (100%) diff --git a/src/Rotations.jl b/src/Rotations.jl index 22cfd9bd..ff7c2f88 100644 --- a/src/Rotations.jl +++ b/src/Rotations.jl @@ -23,7 +23,7 @@ include("rodrigues_params.jl") include("error_maps.jl") include("rotation_error.jl") include("rotation_generator.jl") -include("logexp.jl") +include("elementary_functions.jl") include("eigen.jl") include("rand.jl") include("rotation_between.jl") diff --git a/src/logexp.jl b/src/elementary_functions.jl similarity index 100% rename from src/logexp.jl rename to src/elementary_functions.jl diff --git a/test/logexp.jl b/test/elementary_functions.jl similarity index 100% rename from test/logexp.jl rename to test/elementary_functions.jl diff --git a/test/runtests.jl b/test/runtests.jl index 5e2909b4..1cebd2ed 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -23,7 +23,7 @@ include("distribution_tests.jl") include("eigen.jl") include("nearest_rotation.jl") include("rotation_generator.jl") -include("logexp.jl") +include("elementary_functions.jl") include("deprecated.jl") include(joinpath(@__DIR__, "..", "perf", "runbenchmarks.jl")) From db99a4446e5debb34da0c7504e83c2d12b66102c Mon Sep 17 00:00:00 2001 From: Yuto Horikawa Date: Wed, 20 Sep 2023 22:00:58 +0900 Subject: [PATCH 02/12] add sqrt method --- src/elementary_functions.jl | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/elementary_functions.jl b/src/elementary_functions.jl index f3c4b0d5..644d0687 100644 --- a/src/elementary_functions.jl +++ b/src/elementary_functions.jl @@ -40,3 +40,23 @@ Base.exp(R::RotMatrixGenerator{3}) = RotMatrix(exp(RotationVecGenerator(R))) # General dimensions Base.exp(R::RotMatrixGenerator{N}) where N = RotMatrix(exp(SMatrix(R))) + +## sqrt +# 2d +Base.sqrt(r::Angle2d) = Angle2d(r.theta/2) +Base.sqrt(r::RotMatrix{2}) = RotMatrix(sqrt(Angle2d(r))) + +# 3d +Base.sqrt(r::RotX) = RotX(r.theta/2) +Base.sqrt(r::RotY) = RotY(r.theta/2) +Base.sqrt(r::RotZ) = RotZ(r.theta/2) +Base.sqrt(r::AngleAxis) = AngleAxis(r.theta/2, r.axis_x, r.axis_y, r.axis_z) +Base.sqrt(r::RotationVec) = RotaitonVec(r.sx, r.sy, r.sz) +Base.sqrt(r::QuatRotation) = QuatRotation(sqrt(r.q)) +Base.sqrt(r::RotMatrix{3}) = RotMatrix{3}(sqrt(QuatRotation(r))) +Base.sqrt(r::RodriguesParam) = RodriguesParam(sqrt(QuatRotation(r))) +Base.sqrt(r::MRP) = MRP(sqrt(QuatRotation(r))) +Base.sqrt(r::Rotation{3}) = sqrt(QuatRotation(r)) + +# General dimensions +Base.sqrt(r::Rotation{N}) where N = RotMatrix(sqrt(r)) From ea860537dba6a0a6561bf4b25474f5d7ec2aaa5f Mon Sep 17 00:00:00 2001 From: Yuto Horikawa Date: Wed, 20 Sep 2023 22:06:29 +0900 Subject: [PATCH 03/12] fix sqrt method --- src/elementary_functions.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/elementary_functions.jl b/src/elementary_functions.jl index 644d0687..bd8efd40 100644 --- a/src/elementary_functions.jl +++ b/src/elementary_functions.jl @@ -51,7 +51,7 @@ Base.sqrt(r::RotX) = RotX(r.theta/2) Base.sqrt(r::RotY) = RotY(r.theta/2) Base.sqrt(r::RotZ) = RotZ(r.theta/2) Base.sqrt(r::AngleAxis) = AngleAxis(r.theta/2, r.axis_x, r.axis_y, r.axis_z) -Base.sqrt(r::RotationVec) = RotaitonVec(r.sx, r.sy, r.sz) +Base.sqrt(r::RotationVec) = RotaitonVec(r.sx/2, r.sy/2, r.sz/2) Base.sqrt(r::QuatRotation) = QuatRotation(sqrt(r.q)) Base.sqrt(r::RotMatrix{3}) = RotMatrix{3}(sqrt(QuatRotation(r))) Base.sqrt(r::RodriguesParam) = RodriguesParam(sqrt(QuatRotation(r))) From daa50b199dc28abfaad7769942e86484470b13d1 Mon Sep 17 00:00:00 2001 From: Yuto Horikawa Date: Wed, 20 Sep 2023 22:07:35 +0900 Subject: [PATCH 04/12] add cbrt method --- src/elementary_functions.jl | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/elementary_functions.jl b/src/elementary_functions.jl index bd8efd40..a25d02e0 100644 --- a/src/elementary_functions.jl +++ b/src/elementary_functions.jl @@ -60,3 +60,23 @@ Base.sqrt(r::Rotation{3}) = sqrt(QuatRotation(r)) # General dimensions Base.sqrt(r::Rotation{N}) where N = RotMatrix(sqrt(r)) + +## cbrt +# 2d +Base.cbrt(r::Angle2d) = Angle2d(r.theta/3) +Base.cbrt(r::RotMatrix{2}) = RotMatrix(cbrt(Angle2d(r))) + +# 3d +Base.cbrt(r::RotX) = RotX(r.theta/3) +Base.cbrt(r::RotY) = RotY(r.theta/3) +Base.cbrt(r::RotZ) = RotZ(r.theta/3) +Base.cbrt(r::AngleAxis) = AngleAxis(r.theta/3, r.axis_x, r.axis_y, r.axis_z) +Base.cbrt(r::RotationVec) = RotaitonVec(r.sx/3, r.sy/3, r.sz/3) +Base.cbrt(r::QuatRotation) = QuatRotation(cbrt(r.q)) +Base.cbrt(r::RotMatrix{3}) = RotMatrix{3}(cbrt(QuatRotation(r))) +Base.cbrt(r::RodriguesParam) = RodriguesParam(cbrt(QuatRotation(r))) +Base.cbrt(r::MRP) = MRP(cbrt(QuatRotation(r))) +Base.cbrt(r::Rotation{3}) = cbrt(QuatRotation(r)) + +# General dimensions +Base.cbrt(r::Rotation{N}) where N = exp(log(r)/3) From 71ebd5f1c043edc5387ef5dd560715f02262aaa9 Mon Sep 17 00:00:00 2001 From: Yuto Horikawa Date: Wed, 20 Sep 2023 22:20:42 +0900 Subject: [PATCH 05/12] add power methods --- src/angleaxis_types.jl | 5 ----- src/core_types.jl | 2 -- src/elementary_functions.jl | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/angleaxis_types.jl b/src/angleaxis_types.jl index b4511623..3c45605a 100644 --- a/src/angleaxis_types.jl +++ b/src/angleaxis_types.jl @@ -125,9 +125,6 @@ end @inline Base.:*(aa1::AngleAxis, aa2::AngleAxis) = QuatRotation(aa1) * QuatRotation(aa2) @inline Base.inv(aa::AngleAxis) = AngleAxis(-aa.theta, aa.axis_x, aa.axis_y, aa.axis_z) -@inline Base.:^(aa::AngleAxis, t::Real) = AngleAxis(aa.theta*t, aa.axis_x, aa.axis_y, aa.axis_z) -@inline Base.:^(aa::AngleAxis, t::Integer) = AngleAxis(aa.theta*t, aa.axis_x, aa.axis_y, aa.axis_z) # to avoid ambiguity - # define identity rotations for convenience @inline Base.one(::Type{AngleAxis}) = AngleAxis(0.0, 1.0, 0.0, 0.0) @@ -204,8 +201,6 @@ end @inline Base.:*(rv1::RotationVec, rv2::RotationVec) = QuatRotation(rv1) * QuatRotation(rv2) @inline Base.inv(rv::RotationVec) = RotationVec(-rv.sx, -rv.sy, -rv.sz) -@inline Base.:^(rv::RotationVec, t::Real) = RotationVec(rv.sx*t, rv.sy*t, rv.sz*t) -@inline Base.:^(rv::RotationVec, t::Integer) = RotationVec(rv.sx*t, rv.sy*t, rv.sz*t) # to avoid ambiguity # rotation properties @inline rotation_angle(rv::RotationVec) = sqrt(rv.sx * rv.sx + rv.sy * rv.sy + rv.sz * rv.sz) diff --git a/src/core_types.jl b/src/core_types.jl index 1c5900a6..5238987c 100644 --- a/src/core_types.jl +++ b/src/core_types.jl @@ -175,8 +175,6 @@ end end Base.:*(r1::Angle2d, r2::Angle2d) = Angle2d(r1.theta + r2.theta) -Base.:^(r::Angle2d, t::Real) = Angle2d(r.theta*t) -Base.:^(r::Angle2d, t::Integer) = Angle2d(r.theta*t) Base.inv(r::Angle2d) = Angle2d(-r.theta) @inline function Base.getindex(r::Angle2d, i::Int) diff --git a/src/elementary_functions.jl b/src/elementary_functions.jl index a25d02e0..c67d4f28 100644 --- a/src/elementary_functions.jl +++ b/src/elementary_functions.jl @@ -80,3 +80,36 @@ Base.cbrt(r::Rotation{3}) = cbrt(QuatRotation(r)) # General dimensions Base.cbrt(r::Rotation{N}) where N = exp(log(r)/3) + +## power +# 2d +Base.:^(r::Angle2d, p::Real) = Angle2d(r.theta*p) +Base.:^(r::Angle2d, p::Integer) = Angle2d(r.theta*p) +Base.:^(r::RotMatrix{2}, p::Real) = RotMatrix(Angle2d(r)^p) +Base.:^(r::RotMatrix{2}, p::Integer) = RotMatrix(Angle2d(r)^p) + +# 3d +Base.:^(r::RotX, p::Real) = RotX(r.theta*p) +Base.:^(r::RotX, p::Integer) = RotX(r.theta*p) +Base.:^(r::RotY, p::Real) = RotY(r.theta*p) +Base.:^(r::RotY, p::Integer) = RotY(r.theta*p) +Base.:^(r::RotZ, p::Real) = RotZ(r.theta*p) +Base.:^(r::RotZ, p::Integer) = RotZ(r.theta*p) +Base.:^(r::AngleAxis, p::Real) = AngleAxis(r.theta*p, r.axis_x, r.axis_y, r.axis_z) +Base.:^(r::AngleAxis, p::Integer) = AngleAxis(r.theta*p, r.axis_x, r.axis_y, r.axis_z) +Base.:^(r::RotationVec, p::Real) = RotaitonVec(r.sx*p, r.sy*p, r.sz*p) +Base.:^(r::RotationVec, p::Integer) = RotaitonVec(r.sx*p, r.sy*p, r.sz*p) +Base.:^(r::QuatRotation, p::Real) = QuatRotation((r.q)^p) +Base.:^(r::QuatRotation, p::Integer) = QuatRotation((r.q)^p) +Base.:^(r::RotMatrix{3}, p::Real) = RotMatrix{3}(QuatRotation(r)^p) +Base.:^(r::RotMatrix{3}, p::Integer) = RotMatrix{3}(QuatRotation(r)^p) +Base.:^(r::RodriguesParam, p::Real) = RodriguesParam(QuatRotation(r)^p) +Base.:^(r::RodriguesParam, p::Integer) = RodriguesParam(QuatRotation(r)^p) +Base.:^(r::MRP, p::Real) = MRP(QuatRotation(r)^p) +Base.:^(r::MRP, p::Integer) = MRP(QuatRotation(r)^p) +Base.:^(r::Rotation{3}, p::Real) = QuatRotation(r)^p +Base.:^(r::Rotation{3}, p::Integer) = QuatRotation(r)^p + +# General dimensions +Base.:^(r::Rotation{N}, p::Real) where N = exp(log(r)*p) +Base.:^(r::Rotation{N}, p::Integer) where N = Rotation{N}(r^p) From 0dd6a4284d91e12d998571a48c5a45c77e7aeae8 Mon Sep 17 00:00:00 2001 From: hyrodium Date: Thu, 21 Sep 2023 01:35:34 +0900 Subject: [PATCH 06/12] add tests for sqrt --- test/elementary_functions.jl | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/elementary_functions.jl b/test/elementary_functions.jl index f86af96e..bec31dea 100644 --- a/test/elementary_functions.jl +++ b/test/elementary_functions.jl @@ -41,3 +41,38 @@ end @test exp(r) isa RotMatrix{N} end end + +@testset "sqrt" begin + all_types = ( + RotMatrix3, RotMatrix{3}, AngleAxis, RotationVec, + QuatRotation, RodriguesParam, MRP, + RotXYZ, RotYZX, RotZXY, RotXZY, RotYXZ, RotZYX, + RotXYX, RotYZY, RotZXZ, RotXZX, RotYXY, RotZYZ, + RotX, RotY, RotZ, + RotXY, RotYZ, RotZX, RotXZ, RotYX, RotZY, + RotMatrix2, RotMatrix{2}, Angle2d + ) + + compat_types = ( + RotMatrix3, RotMatrix{3}, AngleAxis, RotationVec, + QuatRotation, RodriguesParam, MRP, + RotX, RotY, RotZ, + RotMatrix2, RotMatrix{2}, Angle2d + ) + + @testset "$(T)" for T in all_types, F in (one, rand) + R = F(T) + @test R ≈ sqrt(R) * sqrt(R) + @test sqrt(R) isa Rotation + end + + @testset "$(T)-compat" for T in compat_types + R = one(T) + @test sqrt(R) isa T + end + + @testset "$(T)-noncompat3d" for T in setdiff(all_types, compat_types) + R = one(T) + @test sqrt(R) isa QuatRotation + end +end From 249e0a50363ebd73ae46f415652e011ac3ced77e Mon Sep 17 00:00:00 2001 From: hyrodium Date: Thu, 21 Sep 2023 01:35:43 +0900 Subject: [PATCH 07/12] fix typos --- src/elementary_functions.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/elementary_functions.jl b/src/elementary_functions.jl index c67d4f28..00d289f3 100644 --- a/src/elementary_functions.jl +++ b/src/elementary_functions.jl @@ -51,7 +51,7 @@ Base.sqrt(r::RotX) = RotX(r.theta/2) Base.sqrt(r::RotY) = RotY(r.theta/2) Base.sqrt(r::RotZ) = RotZ(r.theta/2) Base.sqrt(r::AngleAxis) = AngleAxis(r.theta/2, r.axis_x, r.axis_y, r.axis_z) -Base.sqrt(r::RotationVec) = RotaitonVec(r.sx/2, r.sy/2, r.sz/2) +Base.sqrt(r::RotationVec) = RotationVec(r.sx/2, r.sy/2, r.sz/2) Base.sqrt(r::QuatRotation) = QuatRotation(sqrt(r.q)) Base.sqrt(r::RotMatrix{3}) = RotMatrix{3}(sqrt(QuatRotation(r))) Base.sqrt(r::RodriguesParam) = RodriguesParam(sqrt(QuatRotation(r))) @@ -71,7 +71,7 @@ Base.cbrt(r::RotX) = RotX(r.theta/3) Base.cbrt(r::RotY) = RotY(r.theta/3) Base.cbrt(r::RotZ) = RotZ(r.theta/3) Base.cbrt(r::AngleAxis) = AngleAxis(r.theta/3, r.axis_x, r.axis_y, r.axis_z) -Base.cbrt(r::RotationVec) = RotaitonVec(r.sx/3, r.sy/3, r.sz/3) +Base.cbrt(r::RotationVec) = RotationVec(r.sx/3, r.sy/3, r.sz/3) Base.cbrt(r::QuatRotation) = QuatRotation(cbrt(r.q)) Base.cbrt(r::RotMatrix{3}) = RotMatrix{3}(cbrt(QuatRotation(r))) Base.cbrt(r::RodriguesParam) = RodriguesParam(cbrt(QuatRotation(r))) @@ -97,8 +97,8 @@ Base.:^(r::RotZ, p::Real) = RotZ(r.theta*p) Base.:^(r::RotZ, p::Integer) = RotZ(r.theta*p) Base.:^(r::AngleAxis, p::Real) = AngleAxis(r.theta*p, r.axis_x, r.axis_y, r.axis_z) Base.:^(r::AngleAxis, p::Integer) = AngleAxis(r.theta*p, r.axis_x, r.axis_y, r.axis_z) -Base.:^(r::RotationVec, p::Real) = RotaitonVec(r.sx*p, r.sy*p, r.sz*p) -Base.:^(r::RotationVec, p::Integer) = RotaitonVec(r.sx*p, r.sy*p, r.sz*p) +Base.:^(r::RotationVec, p::Real) = RotationVec(r.sx*p, r.sy*p, r.sz*p) +Base.:^(r::RotationVec, p::Integer) = RotationVec(r.sx*p, r.sy*p, r.sz*p) Base.:^(r::QuatRotation, p::Real) = QuatRotation((r.q)^p) Base.:^(r::QuatRotation, p::Integer) = QuatRotation((r.q)^p) Base.:^(r::RotMatrix{3}, p::Real) = RotMatrix{3}(QuatRotation(r)^p) From f489cbca4bfe1d82fc06aab7bb1cda07416e4240 Mon Sep 17 00:00:00 2001 From: hyrodium Date: Thu, 21 Sep 2023 02:34:01 +0900 Subject: [PATCH 08/12] comment out some `cbrt` methods that requires `cbrt(::Quaternion)` --- src/elementary_functions.jl | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/elementary_functions.jl b/src/elementary_functions.jl index 00d289f3..d4b524b8 100644 --- a/src/elementary_functions.jl +++ b/src/elementary_functions.jl @@ -72,11 +72,12 @@ Base.cbrt(r::RotY) = RotY(r.theta/3) Base.cbrt(r::RotZ) = RotZ(r.theta/3) Base.cbrt(r::AngleAxis) = AngleAxis(r.theta/3, r.axis_x, r.axis_y, r.axis_z) Base.cbrt(r::RotationVec) = RotationVec(r.sx/3, r.sy/3, r.sz/3) -Base.cbrt(r::QuatRotation) = QuatRotation(cbrt(r.q)) -Base.cbrt(r::RotMatrix{3}) = RotMatrix{3}(cbrt(QuatRotation(r))) -Base.cbrt(r::RodriguesParam) = RodriguesParam(cbrt(QuatRotation(r))) -Base.cbrt(r::MRP) = MRP(cbrt(QuatRotation(r))) -Base.cbrt(r::Rotation{3}) = cbrt(QuatRotation(r)) +# We can implement these `cbrt` methods when https://github.com/JuliaLang/julia/issues/36534 is resolved. +# Base.cbrt(r::QuatRotation) = QuatRotation(cbrt(r.q)) +# Base.cbrt(r::RotMatrix{3}) = RotMatrix{3}(cbrt(QuatRotation(r))) +# Base.cbrt(r::RodriguesParam) = RodriguesParam(cbrt(QuatRotation(r))) +# Base.cbrt(r::MRP) = MRP(cbrt(QuatRotation(r))) +# Base.cbrt(r::Rotation{3}) = cbrt(QuatRotation(r)) # General dimensions Base.cbrt(r::Rotation{N}) where N = exp(log(r)/3) From f4856cec9830f63816ff4714aeb2dd38bd99471e Mon Sep 17 00:00:00 2001 From: hyrodium Date: Thu, 21 Sep 2023 02:35:13 +0900 Subject: [PATCH 09/12] add tests for cbrt --- test/elementary_functions.jl | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/elementary_functions.jl b/test/elementary_functions.jl index bec31dea..37df53ad 100644 --- a/test/elementary_functions.jl +++ b/test/elementary_functions.jl @@ -76,3 +76,17 @@ end @test sqrt(R) isa QuatRotation end end + +@testset "cbrt" begin + supported_types = ( + AngleAxis, RotationVec, + RotX, RotY, RotZ, + RotMatrix2, RotMatrix{2}, Angle2d + ) + + @testset "$(T)" for T in supported_types, F in (one, rand) + R = F(T) + @test R ≈ cbrt(R) * cbrt(R) * cbrt(R) + @test cbrt(R) isa Rotation + end +end From e8f39da35c9de5d2252e50ed8201a98c923029c4 Mon Sep 17 00:00:00 2001 From: hyrodium Date: Thu, 21 Sep 2023 12:10:55 +0900 Subject: [PATCH 10/12] add tests for power(`^`) --- test/elementary_functions.jl | 38 ++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/test/elementary_functions.jl b/test/elementary_functions.jl index 37df53ad..6bdf3bd0 100644 --- a/test/elementary_functions.jl +++ b/test/elementary_functions.jl @@ -90,3 +90,41 @@ end @test cbrt(R) isa Rotation end end + +@testset "power" begin + all_types = ( + RotMatrix3, RotMatrix{3}, AngleAxis, RotationVec, + QuatRotation, RodriguesParam, MRP, + RotXYZ, RotYZX, RotZXY, RotXZY, RotYXZ, RotZYX, + RotXYX, RotYZY, RotZXZ, RotXZX, RotYXY, RotZYZ, + RotX, RotY, RotZ, + RotXY, RotYZ, RotZX, RotXZ, RotYX, RotZY, + RotMatrix2, RotMatrix{2}, Angle2d + ) + + compat_types = ( + RotMatrix3, RotMatrix{3}, AngleAxis, RotationVec, + QuatRotation, RodriguesParam, MRP, + RotX, RotY, RotZ, + RotMatrix2, RotMatrix{2}, Angle2d + ) + + @testset "$(T)" for T in all_types, F in (one, rand) + R = F(T) + @test R^2 ≈ R * R + @test R^1.5 ≈ sqrt(R) * sqrt(R) * sqrt(R) + @test R isa Rotation + end + + @testset "$(T)-compat" for T in compat_types + R = one(T) + @test R^2 isa T + @test R^1.5 isa T + end + + @testset "$(T)-noncompat3d" for T in setdiff(all_types, compat_types) + R = one(T) + @test R^2 isa QuatRotation + @test R^1.5 isa QuatRotation + end +end From 5e1eeaf033ea548e64847847576c93e18476d24b Mon Sep 17 00:00:00 2001 From: hyrodium Date: Thu, 21 Sep 2023 12:49:58 +0900 Subject: [PATCH 11/12] add tests for general dimensions --- test/elementary_functions.jl | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/elementary_functions.jl b/test/elementary_functions.jl index 6bdf3bd0..5bcca4b3 100644 --- a/test/elementary_functions.jl +++ b/test/elementary_functions.jl @@ -75,6 +75,13 @@ end R = one(T) @test sqrt(R) isa QuatRotation end + + @testset "$(N)-dim" for N in 1:5 + M = @SMatrix rand(N,N) + R = nearest_rotation(M) + @test R ≈ sqrt(R) * sqrt(R) + @test sqrt(R) isa RotMatrix{N} + end end @testset "cbrt" begin @@ -89,6 +96,13 @@ end @test R ≈ cbrt(R) * cbrt(R) * cbrt(R) @test cbrt(R) isa Rotation end + + @testset "$(N)-dim" for N in 1:5 + M = @SMatrix rand(N,N) + R = nearest_rotation(M) + @test R ≈ cbrt(R) * cbrt(R) * cbrt(R) + @test cbrt(R) isa RotMatrix{N} + end end @testset "power" begin @@ -127,4 +141,13 @@ end @test R^2 isa QuatRotation @test R^1.5 isa QuatRotation end + + @testset "$(N)-dim" for N in 1:5 + M = @SMatrix rand(N,N) + R = nearest_rotation(M) + @test R^2 ≈ R * R + @test R^1.5 ≈ sqrt(R) * sqrt(R) * sqrt(R) + @test R^2 isa RotMatrix{N} + @test R^1.5 isa RotMatrix{N} + end end From 149cc7a7e324c3a2e6776c0bd1ebc0cb1afa9d6d Mon Sep 17 00:00:00 2001 From: hyrodium Date: Thu, 21 Sep 2023 16:14:39 +0900 Subject: [PATCH 12/12] fix methods for general dimensions --- src/elementary_functions.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/elementary_functions.jl b/src/elementary_functions.jl index d4b524b8..ff28d841 100644 --- a/src/elementary_functions.jl +++ b/src/elementary_functions.jl @@ -59,7 +59,7 @@ Base.sqrt(r::MRP) = MRP(sqrt(QuatRotation(r))) Base.sqrt(r::Rotation{3}) = sqrt(QuatRotation(r)) # General dimensions -Base.sqrt(r::Rotation{N}) where N = RotMatrix(sqrt(r)) +Base.sqrt(r::Rotation{N}) where N = RotMatrix(sqrt(SMatrix(r))) ## cbrt # 2d @@ -113,4 +113,5 @@ Base.:^(r::Rotation{3}, p::Integer) = QuatRotation(r)^p # General dimensions Base.:^(r::Rotation{N}, p::Real) where N = exp(log(r)*p) -Base.:^(r::Rotation{N}, p::Integer) where N = Rotation{N}(r^p) +# There is the same implementation of ^(r::Rotation{N}, p::Integer) as in Base +Base.:^(A::Rotation{N}, p::Integer) where N = p < 0 ? Base.power_by_squaring(inv(A), -p) : Base.power_by_squaring(A, p)