Skip to content

Commit 894f524

Browse files
authored
Remove norm field in Quaternion (#243)
* remove .norm field in Quaternion * update constructors of QuatRotation * update unittest on QuatRotation * avoid unnecessary normalizations in QuatRotation * remove _normalize(::QuatRotation)
1 parent 9fb1e91 commit 894f524

File tree

3 files changed

+18
-35
lines changed

3 files changed

+18
-35
lines changed

src/rand.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,6 @@ end
6666
end
6767

6868
function Random.rand(rng::AbstractRNG, ::Random.SamplerType{<:QuatRotation{T}}) where T
69-
_normalize(QuatRotation{T}(randn(rng,T), randn(rng,T), randn(rng,T), randn(rng,T)))
69+
q = Quaternion(randn(rng,T), randn(rng,T), randn(rng,T), randn(rng,T))
70+
return QuatRotation{T}(sign(q))
7071
end

src/unitquaternion.jl

Lines changed: 15 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,19 @@ Follows the Hamilton convention for quaternions.
1111
QuatRotation(w,x,y,z)
1212
QuatRotation(q::AbstractVector)
1313
```
14-
where `w` is the scalar (real) part, `x`,`y`, and `z` are the vector (imaginary) part,
14+
where `w` is the scalar (real) part, `x`, `y`, and `z` are the vector (imaginary) part,
1515
and `q = [w,x,y,z]`.
1616
"""
1717
struct QuatRotation{T} <: Rotation{3,T}
1818
q::Quaternion{T}
1919

20-
@inline function QuatRotation{T}(w, x, y, z, normalize::Bool = true) where T
20+
@inline function QuatRotation{T}(q::Quaternion, normalize::Bool = true) where T
2121
if normalize
22-
inorm = inv(sqrt(w*w + x*x + y*y + z*z))
23-
new{T}(Quaternion(w*inorm, x*inorm, y*inorm, z*inorm, true))
22+
new{T}(sign(q))
2423
else
25-
new{T}(Quaternion(w, x, y, z, true))
26-
end
27-
end
28-
29-
@inline function QuatRotation{T}(q::Quaternion) where T
30-
if q.norm
3124
new{T}(q)
32-
else
33-
throw(InexactError(nameof(T), T, q))
3425
end
3526
end
36-
QuatRotation{T}(q::QuatRotation) where T = new{T}(q.q)
3727
end
3828

3929
function Base.getproperty(q::QuatRotation, f::Symbol)
@@ -52,17 +42,16 @@ end
5242

5343
# ~~~~~~~~~~~~~~~ Constructors ~~~~~~~~~~~~~~~ #
5444
# Use default map
45+
function QuatRotation{T}(w,x,y,z, normalize::Bool = true) where T
46+
QuatRotation{T}(Quaternion(w,x,y,z), normalize)
47+
end
5548
function QuatRotation(w,x,y,z, normalize::Bool = true)
5649
types = promote(w,x,y,z)
57-
QuatRotation{eltype(types)}(w,x,y,z, normalize)
50+
QuatRotation{float(eltype(types))}(w,x,y,z, normalize)
5851
end
5952

60-
function QuatRotation(q::T) where T<:Quaternion
61-
if q.norm
62-
return QuatRotation(real(q), imag_part(q)..., false)
63-
else
64-
throw(InexactError(nameof(T), T, q))
65-
end
53+
function QuatRotation(q::Quaternion{T}, normalize::Bool = true) where T<:Real
54+
return QuatRotation{float(T)}(q, normalize)
6655
end
6756

6857
function Quaternions.Quaternion(q::QuatRotation)
@@ -84,6 +73,7 @@ end
8473

8574
# Copy constructors
8675
QuatRotation(q::QuatRotation) = q
76+
QuatRotation{T}(q::QuatRotation) where T = QuatRotation{T}(q.q)
8777

8878
# QuatRotation <=> Quat
8979
# (::Type{Q})(q::Quat) where Q <: QuatRotation = Q(q.w, q.x, q.y, q.z, false)
@@ -233,21 +223,13 @@ Rotations.params(p) == @SVector [1.0, 2.0, 3.0] # true
233223
@inline params(q::QuatRotation) = SVector{4}(real(q.q), imag_part(q.q)...)
234224

235225
# ~~~~~~~~~~~~~~~ Initializers ~~~~~~~~~~~~~~~ #
236-
@inline Base.one(::Type{Q}) where Q <: QuatRotation = Q(1.0, 0.0, 0.0, 0.0)
226+
@inline Base.one(::Type{Q}) where Q <: QuatRotation = Q(1.0, 0.0, 0.0, 0.0, false)
237227

238228

239229
# ~~~~~~~~~~~~~~~ Math Operations ~~~~~~~~~~~~~~~ #
240230

241231
# Inverses
242-
Base.inv(q::Q) where Q <: QuatRotation = Q(conj(q.q))
243-
244-
function _normalize(q::Q) where Q <: QuatRotation
245-
w = real(q.q)
246-
x, y, z = imag_part(q.q)
247-
248-
n = norm(params(q))
249-
Q(w/n, x/n, y/n, z/n)
250-
end
232+
Base.inv(q::Q) where Q <: QuatRotation = Q(conj(q.q), false)
251233

252234
# Identity
253235
(::Type{Q})(I::UniformScaling) where Q <: QuatRotation = one(Q)
@@ -261,11 +243,11 @@ Create a `Quaternion` with zero scalar part (i.e. `q.q.s == 0`).
261243
"""
262244
function pure_quaternion(v::AbstractVector)
263245
check_length(v, 3)
264-
Quaternion(zero(eltype(v)), v[1], v[2], v[3], false)
246+
Quaternion(zero(eltype(v)), v[1], v[2], v[3])
265247
end
266248

267249
@inline pure_quaternion(x::Real, y::Real, z::Real) =
268-
Quaternion(zero(x), x, y, z, false)
250+
Quaternion(zero(x), x, y, z)
269251

270252
function expm::AbstractVector)
271253
check_length(ϕ, 3)
@@ -309,7 +291,7 @@ rmult(w) * SVector(q)
309291
Sets the output mapping equal to the mapping of `w`
310292
"""
311293
function Base.:*(q1::QuatRotation, q2::QuatRotation)
312-
return QuatRotation(q1.q*q2.q)
294+
return QuatRotation(q1.q * q2.q, false)
313295
end
314296

315297
"""

test/unitquat.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import Rotations: vmat, rmult, lmult, hmat, tmat
1414
@test QuatRotation(1.0, 0.0, 0.0, 0.0) isa QuatRotation{Float64}
1515
@test QuatRotation(1.0, 0, 0, 0) isa QuatRotation{Float64}
1616
@test QuatRotation(1.0, 0, 0, 0) isa QuatRotation{Float64}
17-
@test QuatRotation(1, 0, 0, 0) isa QuatRotation{Int}
17+
@test QuatRotation(1, 0, 0, 0) isa QuatRotation{Float64}
1818
@test QuatRotation(1.0f0, 0, 0, 0) isa QuatRotation{Float32}
1919

2020
q = normalize(@SVector rand(4))

0 commit comments

Comments
 (0)