@@ -13,7 +13,6 @@ struct Quaternion{T<:Real} <: Number
1313 v1:: T
1414 v2:: T
1515 v3:: T
16- norm:: Bool
1716end
1817
1918const QuaternionF16 = Quaternion{Float16}
@@ -25,15 +24,12 @@ function Quaternion{T}(x::Complex) where {T<:Real}
2524 Base. depwarn (" `Complex`-`Quaternion` compatibility is deprecated and will be removed in the next breaking release (v0.7.0)." , :Quaternion )
2625 Quaternion (convert (Complex{T}, x))
2726end
28- Quaternion {T} (q:: Quaternion ) where {T<: Real } = Quaternion {T} (q. s, q. v1, q. v2, q. v3, q. norm)
29- function Quaternion (s:: Real , v1:: Real , v2:: Real , v3:: Real , n:: Bool = false )
30- Base. depwarn (" The `norm` field is deprecated and will be removed in the next breaking release (v0.7.0)." , :Quaternion )
31- Quaternion (promote (s, v1, v2, v3)... , n)
32- end
33- Quaternion (x:: Real ) = Quaternion (x, zero (x), zero (x), zero (x), abs (x) == one (x))
27+ Quaternion {T} (q:: Quaternion ) where {T<: Real } = Quaternion {T} (q. s, q. v1, q. v2, q. v3)
28+ Quaternion (s:: Real , v1:: Real , v2:: Real , v3:: Real ) = Quaternion (promote (s, v1, v2, v3)... )
29+ Quaternion (x:: Real ) = Quaternion (x, zero (x), zero (x), zero (x))
3430function Quaternion (z:: Complex )
3531 Base. depwarn (" `Complex`-`Quaternion` compatibility is deprecated and will be removed in the next breaking release (v0.7.0)." , :Quaternion )
36- Quaternion (z. re, z. im, zero (z. re), zero (z. re), abs (z) == one (z . re) )
32+ Quaternion (z. re, z. im, zero (z. re), zero (z. re))
3733end
3834function Quaternion (s:: Real , a:: AbstractVector )
3935 Base. depwarn (" `Quaternion(s::Real, a::AbstractVector)` is deprecated and will be removed in the next breaking release (v0.7.0). Please use `Quaternion(s, a[1], a[2], a[3])` instead." , :Quaternion )
@@ -51,15 +47,6 @@ function Base.promote_rule(::Type{Quaternion{T}}, ::Type{Complex{S}}) where {T <
5147end
5248Base. promote_rule (:: Type{Quaternion{T}} , :: Type{Quaternion{S}} ) where {T <: Real , S <: Real } = Quaternion{promote_type (T, S)}
5349
54- function Base. getproperty (q:: Quaternion , s:: Symbol )
55- if s === :norm
56- Base. depwarn (" The `norm` field is deprecated and will be removed in the next breaking release (v0.7.0)." , :Quaternion )
57- getfield (q,:norm )
58- else
59- getfield (q,s)
60- end
61- end
62-
6350"""
6451 quat(r, [i, j, k])
6552
@@ -68,19 +55,18 @@ Convert real numbers or arrays to quaternion. `i, j, k` defaults to zero.
6855# Examples
6956```jldoctest
7057julia> quat(7)
71- Quaternion{Int64}(7, 0, 0, 0, false )
58+ Quaternion{Int64}(7, 0, 0, 0)
7259
7360julia> quat(1.0, 2, 3, 4)
74- QuaternionF64(1.0, 2.0, 3.0, 4.0, false )
61+ QuaternionF64(1.0, 2.0, 3.0, 4.0)
7562
7663julia> quat([1, 2, 3]) # This output will be changed in the next breaking release for consistency. (#94)
77- Quaternion{Int64}(0, 1, 2, 3, false )
64+ Quaternion{Int64}(0, 1, 2, 3)
7865```
7966"""
8067quat
8168
8269quat (p, v1, v2, v3) = Quaternion (p, v1, v2, v3)
83- quat (p, v1, v2, v3, n) = Quaternion (p, v1, v2, v3, n)
8470quat (x) = Quaternion (x)
8571quat (s, a) = Quaternion (s, a)
8672
@@ -116,7 +102,7 @@ Base.real(q::Quaternion) = q.s
116102
117103"""
118104 real(A::AbstractArray{<:Quaternion})
119-
105+
120106Return an array containing the real part of each quaternion in `A`.
121107
122108# Examples
@@ -158,53 +144,40 @@ Compute the quaternion conjugate of a quaternion `q`.
158144# Examples
159145```jldoctest
160146julia> conj(Quaternion(1,2,3,4))
161- Quaternion{Int64}(1, -2, -3, -4, false )
147+ Quaternion{Int64}(1, -2, -3, -4)
162148```
163149"""
164- Base. conj (q:: Quaternion ) = Quaternion (q. s, - q. v1, - q. v2, - q. v3, q . norm )
150+ Base. conj (q:: Quaternion ) = Quaternion (q. s, - q. v1, - q. v2, - q. v3)
165151Base. abs (q:: Quaternion ) = sqrt (abs2 (q))
166152Base. float (q:: Quaternion{T} ) where T = convert (Quaternion{float (T)}, q)
167153abs_imag (q:: Quaternion ) = sqrt (q. v2 * q. v2 + (q. v1 * q. v1 + q. v3 * q. v3)) # ordered to match abs2
168154Base. abs2 (q:: Quaternion ) = (q. s * q. s + q. v2 * q. v2) + (q. v1 * q. v1 + q. v3 * q. v3)
169- Base. inv (q:: Quaternion ) = q . norm ? conj (q) : conj (q) / abs2 (q)
155+ Base. inv (q:: Quaternion ) = conj (q) / abs2 (q)
170156
171157Base. isreal (q:: Quaternion ) = iszero (q. v1) & iszero (q. v2) & iszero (q. v3)
172- Base. isfinite (q:: Quaternion ) = q . norm | ( isfinite (q. s) & isfinite (q. v1) & isfinite (q. v2) & isfinite (q. v3) )
173- Base. iszero (q:: Quaternion ) = ~ q . norm & iszero (real (q)) & iszero (q. v1) & iszero (q. v2) & iszero (q. v3)
158+ Base. isfinite (q:: Quaternion ) = isfinite (q. s) & isfinite (q. v1) & isfinite (q. v2) & isfinite (q. v3)
159+ Base. iszero (q:: Quaternion ) = iszero (real (q)) & iszero (q. v1) & iszero (q. v2) & iszero (q. v3)
174160Base. isnan (q:: Quaternion ) = isnan (real (q)) | isnan (q. v1) | isnan (q. v2) | isnan (q. v3)
175- Base. isinf (q:: Quaternion ) = ~ q . norm & ( isinf (q. s) | isinf (q. v1) | isinf (q. v2) | isinf (q. v3) )
161+ Base. isinf (q:: Quaternion ) = isinf (q. s) | isinf (q. v1) | isinf (q. v2) | isinf (q. v3)
176162
177- function LinearAlgebra. normalize (q:: Quaternion )
178- Base. depwarn (" `LinearAlgebra.normalize(q::Quaternion)` is deprecated. Please use `sign(q)` instead." , :normalize )
179- if (q. norm)
180- return q
181- end
182- q = q / abs (q)
183- Quaternion (q. s, q. v1, q. v2, q. v3, true )
184- end
163+ # included strictly for documentation; the base implementation is sufficient
164+ """
165+ sign(q::Quaternion) -> Quaternion
185166
186- function normalizea (q:: Quaternion )
187- Base. depwarn (" `normalizea(q::Quaternion)` is deprecated. Please use `sign(q), abs(q)` instead." , :normalizea )
188- if (q. norm)
189- return (q, one (q. s))
190- end
191- a = abs (q)
192- q = q / a
193- (Quaternion (q. s, q. v1, q. v2, q. v3, true ), a)
194- end
167+ Return zero if `q==0` and ``q/|q|`` otherwise.
195168
196- function normalizeq (q:: Quaternion )
197- Base. depwarn (" `normalizeq(q::Quaternion)` is deprecated. Please use `sign(q)` instead." , :normalizea )
198- a = abs (q)
199- if a > 0
200- q = q / a
201- Quaternion (q. s, q. v1, q. v2, q. v3, true )
202- else
203- Quaternion (0.0 , 1.0 , 0.0 , 0.0 , true )
204- end
205- end
169+ # Examples
170+ ```jldoctest
171+ julia> sign(Quaternion(4, 0, 0, 0))
172+ QuaternionF64(1.0, 0.0, 0.0, 0.0)
206173
207- Base.:- (q:: Quaternion ) = Quaternion (- q. s, - q. v1, - q. v2, - q. v3, q. norm)
174+ julia> sign(Quaternion(1, 0, 1, 0))
175+ QuaternionF64(0.7071067811865475, 0.0, 0.7071067811865475, 0.0)
176+ ```
177+ """
178+ sign (:: Quaternion )
179+
180+ Base.:- (q:: Quaternion ) = Quaternion (- q. s, - q. v1, - q. v2, - q. v3)
208181
209182Base.:+ (q:: Quaternion , w:: Quaternion ) =
210183 Quaternion (q. s + w. s, q. v1 + w. v1, q. v2 + w. v2, q. v3 + w. v3)
@@ -217,12 +190,12 @@ function Base.:*(q::Quaternion, w::Quaternion)
217190 v1 = (q. s * w. v1 + q. v1 * w. s) + (q. v2 * w. v3 - q. v3 * w. v2)
218191 v2 = (q. s * w. v2 + q. v2 * w. s) + (q. v3 * w. v1 - q. v1 * w. v3)
219192 v3 = (q. s * w. v3 + q. v3 * w. s) + (q. v1 * w. v2 - q. v2 * w. v1)
220- return Quaternion (s, v1, v2, v3, q . norm & w . norm )
193+ return Quaternion (s, v1, v2, v3)
221194end
222195
223196Base.:/ (q:: Quaternion , w:: Quaternion ) = q * inv (w)
224197
225- Base.:(== )(q:: Quaternion , w:: Quaternion ) = (q. s == w. s) & (q. v1 == w. v1) & (q. v2 == w. v2) & (q. v3 == w. v3) # ignore .norm field
198+ Base.:(== )(q:: Quaternion , w:: Quaternion ) = (q. s == w. s) & (q. v1 == w. v1) & (q. v2 == w. v2) & (q. v3 == w. v3)
226199
227200angleaxis (q:: Quaternion ) = angle (q), axis (q)
228201
@@ -233,18 +206,13 @@ end
233206
234207function axis (q:: Quaternion )
235208 Base. depwarn (" `axis(::Quaternion)` is deprecated. Please consider using Rotations package instead." , :axis )
236- q = normalize (q)
209+ q = sign (q)
237210 s = sin (angle (q) / 2 )
238211 abs (s) > 0 ?
239212 [q. v1, q. v2, q. v3] / s :
240213 [1.0 , 0.0 , 0.0 ]
241214end
242215
243- function argq (q:: Quaternion )
244- Base. depwarn (" `argq(q::Quaternion)` is deprecated. Use `quat(0, imag_part(q)...)` instead." , :argq )
245- normalizeq (Quaternion (0 , q. v1, q. v2, q. v3))
246- end
247-
248216"""
249217 extend_analytic(f, q::Quaternion)
250218
@@ -273,20 +241,16 @@ function extend_analytic(f, q::Quaternion)
273241 w = f (z)
274242 wr, wi = reim (w)
275243 scale = wi / a
276- norm = _isexpfun (f) && iszero (s)
277244 if a > 0
278- return Quaternion (wr, scale * q. v1, scale * q. v2, scale * q. v3, norm )
245+ return Quaternion (wr, scale * q. v1, scale * q. v2, scale * q. v3)
279246 else
280247 # q == real(q), so f(real(q)) may be real or complex, i.e. wi may be nonzero.
281248 # we choose to embed complex numbers in the quaternions by identifying the first
282249 # imaginary quaternion basis with the complex imaginary basis.
283- return Quaternion (wr, oftype (scale, wi), zero (scale), zero (scale), norm )
250+ return Quaternion (wr, oftype (scale, wi), zero (scale), zero (scale))
284251 end
285252end
286253
287- _isexpfun (:: Union{typeof(exp),typeof(exp2),typeof(exp10)} ) = true
288- _isexpfun (:: Any ) = false
289-
290254for f in (
291255 :sqrt , :exp , :exp2 , :exp10 , :expm1 , :log2 , :log10 , :log1p ,
292256 :sin , :cos , :tan , :asin , :acos , :atan , :sinh , :cosh , :tanh , :asinh , :acosh , :atanh ,
@@ -332,10 +296,10 @@ end
332296Base.:^ (q:: Quaternion , w:: Quaternion ) = exp (w * log (q))
333297
334298quatrand (rng = Random. GLOBAL_RNG) = quat (randn (rng), randn (rng), randn (rng), randn (rng))
335- nquatrand (rng = Random. GLOBAL_RNG) = normalize (quatrand (rng))
299+ nquatrand (rng = Random. GLOBAL_RNG) = sign (quatrand (rng))
336300
337301function Base. rand (rng:: AbstractRNG , :: Random.SamplerType{Quaternion{T}} ) where {T<: Real }
338- Quaternion {T} (rand (rng, T), rand (rng, T), rand (rng, T), rand (rng, T), false )
302+ Quaternion {T} (rand (rng, T), rand (rng, T), rand (rng, T), rand (rng, T))
339303end
340304
341305function Base. randn (rng:: AbstractRNG , :: Type{Quaternion{T}} ) where {T<: AbstractFloat }
@@ -344,7 +308,6 @@ function Base.randn(rng::AbstractRNG, ::Type{Quaternion{T}}) where {T<:AbstractF
344308 randn (rng, T) * 1 // 2 ,
345309 randn (rng, T) * 1 // 2 ,
346310 randn (rng, T) * 1 // 2 ,
347- false ,
348311 )
349312end
350313
@@ -362,7 +325,7 @@ function qrotation(axis::AbstractVector{T}, theta) where {T <: Real}
362325 end
363326 s,c = sincos (theta / 2 )
364327 scaleby = s / normaxis
365- Quaternion (c, scaleby * axis[1 ], scaleby * axis[2 ], scaleby * axis[3 ], true )
328+ Quaternion (c, scaleby * axis[1 ], scaleby * axis[2 ], scaleby * axis[3 ])
366329end
367330
368331# Variant of the above where norm(rotvec) encodes theta
@@ -374,7 +337,7 @@ function qrotation(rotvec::AbstractVector{T}) where {T <: Real}
374337 theta = norm (rotvec)
375338 s,c = sincos (theta / 2 )
376339 scaleby = s / (iszero (theta) ? one (theta) : theta)
377- Quaternion (c, scaleby * rotvec[1 ], scaleby * rotvec[2 ], scaleby * rotvec[3 ], true )
340+ Quaternion (c, scaleby * rotvec[1 ], scaleby * rotvec[2 ], scaleby * rotvec[3 ])
378341end
379342
380343function qrotation (dcm:: AbstractMatrix{T} ) where {T<: Real }
@@ -399,9 +362,9 @@ function qrotation(dcm::AbstractMatrix{T}) where {T<:Real}
399362 a,b,c = (dcm[2 ,1 ]- dcm[1 ,2 ])/ 4 d, (dcm[1 ,3 ]+ dcm[3 ,1 ])/ 4 d, (dcm[3 ,2 ]+ dcm[2 ,3 ])/ 4 d
400363 end
401364 if a > 0
402- return Quaternion (a,b,c,d, true )
365+ return Quaternion (a,b,c,d)
403366 else
404- return Quaternion (- a,- b,- c,- d, true )
367+ return Quaternion (- a,- b,- c,- d)
405368 end
406369end
407370
@@ -411,7 +374,7 @@ function qrotation(dcm::AbstractMatrix{T}, qa::Quaternion) where {T<:Real}
411374 abs (q- qa) < abs (q+ qa) ? q : - q
412375end
413376
414- rotationmatrix (q:: Quaternion ) = rotationmatrix_normalized (normalize (q))
377+ rotationmatrix (q:: Quaternion ) = rotationmatrix_normalized (sign (q))
415378
416379function rotationmatrix_normalized (q:: Quaternion )
417380 Base. depwarn (" `rotationmatrix_normalized(::Quaternion)` is deprecated. Please consider using Rotations package instead." , :rotationmatrix_normalized )
@@ -434,13 +397,13 @@ Since the input is normalized inside the function, the absolute value of the ret
434397julia> using Quaternions
435398
436399julia> qa = Quaternion(1,0,0,0)
437- Quaternion{Int64}(1, 0, 0, 0, false )
400+ Quaternion{Int64}(1, 0, 0, 0)
438401
439402julia> qb = Quaternion(0,1,0,0)
440- Quaternion{Int64}(0, 1, 0, 0, false )
403+ Quaternion{Int64}(0, 1, 0, 0)
441404
442405julia> slerp(qa, qb, 0.6)
443- QuaternionF64(0.5877852522924731, 0.8090169943749475, 0.0, 0.0, true )
406+ QuaternionF64(0.5877852522924731, 0.8090169943749475, 0.0, 0.0)
444407
445408julia> ans ≈ Quaternion(cospi(0.3), sinpi(0.3), 0, 0)
446409true
475438 qa. v1 * ratio_a + qb. v1 * ratio_b,
476439 qa. v2 * ratio_a + qb. v2 * ratio_b,
477440 qa. v3 * ratio_a + qb. v3 * ratio_b,
478- true
479441 )
480442end
481443
0 commit comments