@@ -13,7 +13,6 @@ struct Quaternion{T<:Real} <: Number
13
13
v1:: T
14
14
v2:: T
15
15
v3:: T
16
- norm:: Bool
17
16
end
18
17
19
18
const QuaternionF16 = Quaternion{Float16}
@@ -25,15 +24,12 @@ function Quaternion{T}(x::Complex) where {T<:Real}
25
24
Base. depwarn (" `Complex`-`Quaternion` compatibility is deprecated and will be removed in the next breaking release (v0.7.0)." , :Quaternion )
26
25
Quaternion (convert (Complex{T}, x))
27
26
end
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))
34
30
function Quaternion (z:: Complex )
35
31
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))
37
33
end
38
34
function Quaternion (s:: Real , a:: AbstractVector )
39
35
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 <
51
47
end
52
48
Base. promote_rule (:: Type{Quaternion{T}} , :: Type{Quaternion{S}} ) where {T <: Real , S <: Real } = Quaternion{promote_type (T, S)}
53
49
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
-
63
50
"""
64
51
quat(r, [i, j, k])
65
52
@@ -68,19 +55,18 @@ Convert real numbers or arrays to quaternion. `i, j, k` defaults to zero.
68
55
# Examples
69
56
```jldoctest
70
57
julia> quat(7)
71
- Quaternion{Int64}(7, 0, 0, 0, false )
58
+ Quaternion{Int64}(7, 0, 0, 0)
72
59
73
60
julia> 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)
75
62
76
63
julia> 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)
78
65
```
79
66
"""
80
67
quat
81
68
82
69
quat (p, v1, v2, v3) = Quaternion (p, v1, v2, v3)
83
- quat (p, v1, v2, v3, n) = Quaternion (p, v1, v2, v3, n)
84
70
quat (x) = Quaternion (x)
85
71
quat (s, a) = Quaternion (s, a)
86
72
@@ -116,7 +102,7 @@ Base.real(q::Quaternion) = q.s
116
102
117
103
"""
118
104
real(A::AbstractArray{<:Quaternion})
119
-
105
+
120
106
Return an array containing the real part of each quaternion in `A`.
121
107
122
108
# Examples
@@ -158,53 +144,40 @@ Compute the quaternion conjugate of a quaternion `q`.
158
144
# Examples
159
145
```jldoctest
160
146
julia> conj(Quaternion(1,2,3,4))
161
- Quaternion{Int64}(1, -2, -3, -4, false )
147
+ Quaternion{Int64}(1, -2, -3, -4)
162
148
```
163
149
"""
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)
165
151
Base. abs (q:: Quaternion ) = sqrt (abs2 (q))
166
152
Base. float (q:: Quaternion{T} ) where T = convert (Quaternion{float (T)}, q)
167
153
abs_imag (q:: Quaternion ) = sqrt (q. v2 * q. v2 + (q. v1 * q. v1 + q. v3 * q. v3)) # ordered to match abs2
168
154
Base. 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)
170
156
171
157
Base. 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)
174
160
Base. 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)
176
162
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
185
166
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.
195
168
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)
206
173
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)
208
181
209
182
Base.:+ (q:: Quaternion , w:: Quaternion ) =
210
183
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)
217
190
v1 = (q. s * w. v1 + q. v1 * w. s) + (q. v2 * w. v3 - q. v3 * w. v2)
218
191
v2 = (q. s * w. v2 + q. v2 * w. s) + (q. v3 * w. v1 - q. v1 * w. v3)
219
192
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)
221
194
end
222
195
223
196
Base.:/ (q:: Quaternion , w:: Quaternion ) = q * inv (w)
224
197
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)
226
199
227
200
angleaxis (q:: Quaternion ) = angle (q), axis (q)
228
201
@@ -233,18 +206,13 @@ end
233
206
234
207
function axis (q:: Quaternion )
235
208
Base. depwarn (" `axis(::Quaternion)` is deprecated. Please consider using Rotations package instead." , :axis )
236
- q = normalize (q)
209
+ q = sign (q)
237
210
s = sin (angle (q) / 2 )
238
211
abs (s) > 0 ?
239
212
[q. v1, q. v2, q. v3] / s :
240
213
[1.0 , 0.0 , 0.0 ]
241
214
end
242
215
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
-
248
216
"""
249
217
extend_analytic(f, q::Quaternion)
250
218
@@ -273,20 +241,16 @@ function extend_analytic(f, q::Quaternion)
273
241
w = f (z)
274
242
wr, wi = reim (w)
275
243
scale = wi / a
276
- norm = _isexpfun (f) && iszero (s)
277
244
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)
279
246
else
280
247
# q == real(q), so f(real(q)) may be real or complex, i.e. wi may be nonzero.
281
248
# we choose to embed complex numbers in the quaternions by identifying the first
282
249
# 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))
284
251
end
285
252
end
286
253
287
- _isexpfun (:: Union{typeof(exp),typeof(exp2),typeof(exp10)} ) = true
288
- _isexpfun (:: Any ) = false
289
-
290
254
for f in (
291
255
:sqrt , :exp , :exp2 , :exp10 , :expm1 , :log2 , :log10 , :log1p ,
292
256
:sin , :cos , :tan , :asin , :acos , :atan , :sinh , :cosh , :tanh , :asinh , :acosh , :atanh ,
@@ -332,10 +296,10 @@ end
332
296
Base.:^ (q:: Quaternion , w:: Quaternion ) = exp (w * log (q))
333
297
334
298
quatrand (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))
336
300
337
301
function 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))
339
303
end
340
304
341
305
function 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
344
308
randn (rng, T) * 1 // 2 ,
345
309
randn (rng, T) * 1 // 2 ,
346
310
randn (rng, T) * 1 // 2 ,
347
- false ,
348
311
)
349
312
end
350
313
@@ -362,7 +325,7 @@ function qrotation(axis::AbstractVector{T}, theta) where {T <: Real}
362
325
end
363
326
s,c = sincos (theta / 2 )
364
327
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 ])
366
329
end
367
330
368
331
# Variant of the above where norm(rotvec) encodes theta
@@ -374,7 +337,7 @@ function qrotation(rotvec::AbstractVector{T}) where {T <: Real}
374
337
theta = norm (rotvec)
375
338
s,c = sincos (theta / 2 )
376
339
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 ])
378
341
end
379
342
380
343
function qrotation (dcm:: AbstractMatrix{T} ) where {T<: Real }
@@ -399,9 +362,9 @@ function qrotation(dcm::AbstractMatrix{T}) where {T<:Real}
399
362
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
400
363
end
401
364
if a > 0
402
- return Quaternion (a,b,c,d, true )
365
+ return Quaternion (a,b,c,d)
403
366
else
404
- return Quaternion (- a,- b,- c,- d, true )
367
+ return Quaternion (- a,- b,- c,- d)
405
368
end
406
369
end
407
370
@@ -411,7 +374,7 @@ function qrotation(dcm::AbstractMatrix{T}, qa::Quaternion) where {T<:Real}
411
374
abs (q- qa) < abs (q+ qa) ? q : - q
412
375
end
413
376
414
- rotationmatrix (q:: Quaternion ) = rotationmatrix_normalized (normalize (q))
377
+ rotationmatrix (q:: Quaternion ) = rotationmatrix_normalized (sign (q))
415
378
416
379
function rotationmatrix_normalized (q:: Quaternion )
417
380
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
434
397
julia> using Quaternions
435
398
436
399
julia> qa = Quaternion(1,0,0,0)
437
- Quaternion{Int64}(1, 0, 0, 0, false )
400
+ Quaternion{Int64}(1, 0, 0, 0)
438
401
439
402
julia> qb = Quaternion(0,1,0,0)
440
- Quaternion{Int64}(0, 1, 0, 0, false )
403
+ Quaternion{Int64}(0, 1, 0, 0)
441
404
442
405
julia> 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)
444
407
445
408
julia> ans ≈ Quaternion(cospi(0.3), sinpi(0.3), 0, 0)
446
409
true
475
438
qa. v1 * ratio_a + qb. v1 * ratio_b,
476
439
qa. v2 * ratio_a + qb. v2 * ratio_b,
477
440
qa. v3 * ratio_a + qb. v3 * ratio_b,
478
- true
479
441
)
480
442
end
481
443
0 commit comments