@@ -156,22 +156,139 @@ Base.:(/)(a::MyReal, b::Real) = a.val / b
156
156
# this used to throw an error
157
157
@test qrotation ([1 , 0 , 0 ], MyReal (1.5 )) == qrotation ([1 , 0 , 0 ], 1.5 )
158
158
159
- for _ in 1 : 100
160
- let # test specialfunctions
161
- c = Complex ( randn ( 2 ) ... )
162
- q, q2 = sample (Quaternion{Float64}, 4 )
163
- unary_funs = [exp, log, sin, cos, sqrt, inv, conj, abs2, norm]
164
- # since every quaternion is conjugate to a complex number,
165
- # one can establish correctness as follows:
166
- for fun in unary_funs
167
- @test fun (Quaternion (c)) ≈ Quaternion ( fun (c) )
159
+ @testset " non-analytic functions " begin
160
+ q, q2 = randn (Quaternion{Float64}, 2 )
161
+ unary_funs = [conj, abs, abs2, norm, sign]
162
+ # since every quaternion is conjugate to a complex number,
163
+ # one can establish correctness as follows:
164
+ @testset for fun in unary_funs
165
+ for _ in 1 : 100
166
+ c = randn (ComplexF64)
167
+ @test fun (Quaternion (c)) ≈ fun (c)
168
168
@test q2 * fun (q) * inv (q2) ≈ fun (q2 * q * inv (q2))
169
169
end
170
+ end
171
+ end
172
+
173
+ @testset " extended complex analytic functions" begin
174
+ # all complex analytic functions can be extended to the quaternions
175
+ unary_funs = [
176
+ sqrt, inv, exp, exp2, exp10, expm1, log, log2, log10, log1p, cis,
177
+ sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh,
178
+ csc, sec, cot, acsc, asec, acot, csch, sech, coth, acsch, asech, acoth,
179
+ sinpi, cospi,
180
+ ]
181
+ # since every quaternion is conjugate to a complex number,
182
+ # one can establish correctness as follows:
183
+ @testset for fun in unary_funs
184
+ q, q2 = randn (QuaternionF64, 2 )
185
+ for _ in 1 : 100
186
+ c = randn (ComplexF64)
187
+ fun != = cis && @test fun (Quaternion (c)) ≈ fun (c)
188
+ @test q2 * fun (q) * inv (q2) ≈ fun (q2 * q * inv (q2))
189
+ end
190
+ end
170
191
171
- @test exp (log (q)) ≈ q
172
- @test exp (zero (q)) ≈ one (q)
192
+ @testset " identities" begin
193
+ for _ in 1 : 100
194
+ q = randn (QuaternionF64)
195
+ @test inv (q) * q ≈ q * inv (q) ≈ one (q)
196
+ @test sqrt (q) * sqrt (q) ≈ q
197
+ @test exp (log (q)) ≈ q
198
+ @test exp (zero (q)) ≈ one (q)
199
+ @test log (one (q)) ≈ zero (q)
200
+ @test exp2 (log2 (q)) ≈ q
201
+ @test exp10 (log10 (q)) ≈ q
202
+ @test expm1 (log1p (q)) ≈ q
203
+ @test sinpi (q) ≈ sin (π * q)
204
+ @test cospi (q) ≈ cos (π * q)
205
+ @test all (sincos (q) .≈ (sin (q), cos (q)))
206
+ @test all (sincos (zero (q)) .≈ (sin (zero (q)), cos (zero (q))))
207
+ if VERSION ≥ v " 1.6"
208
+ @test all (sincospi (q) .≈ (sinpi (q), cospi (q)))
209
+ @test all (sincospi (zero (q)) .≈ (sinpi (zero (q)), cospi (zero (q))))
210
+ end
211
+ @test tan (q) ≈ cos (q) \ sin (q) ≈ sin (q) / cos (q)
212
+ @test tanh (q) ≈ cosh (q) \ sinh (q) ≈ sinh (q) / cosh (q)
213
+ @testset for (f, finv) in [(sin, csc), (cos, sec), (tan, cot), (sinh, csch), (cosh, sech), (tanh, coth)]
214
+ @test f (q) ≈ inv (finv (q))
215
+ end
216
+ @testset for (f, finv) in [(asin, acsc), (acos, asec), (atan, acot), (asinh, acsch), (acosh, asech), (atanh, acoth)]
217
+ @test f (q) ≈ finv (inv (q))
218
+ end
219
+ @test cis (q) ≈ exp (normalize (q - real (q)) * q)
220
+ VERSION ≥ v " 1.6" && @test cispi (q) ≈ cis (π * q)
221
+ end
173
222
end
174
223
224
+ @testset " additional properties" begin
225
+ @testset " log" begin
226
+ @test log (zero (QuaternionF64)) === Quaternion (- Inf , 0 , 0 , 0 )
227
+ end
228
+
229
+ @testset " exp" begin
230
+ @test exp (Quaternion (0 , 0 , 0 , 0 )) === Quaternion (1. , 0. , 0. , 0. , true )
231
+ @test exp (Quaternion (2 , 0 , 0 , 0 )) === Quaternion (exp (2 ), 0 , 0 , 0 , false )
232
+ @test exp (Quaternion (0 , 2 , 0 , 0 )) === Quaternion (cos (2 ), sin (2 ), 0 , 0 , true )
233
+ @test exp (Quaternion (0 , 0 , 2 , 0 )) === Quaternion (cos (2 ), 0 , sin (2 ), 0 , true )
234
+ @test exp (Quaternion (0 , 0 , 0 , 2 )) === Quaternion (cos (2 ), 0 , 0 , sin (2 ), true )
235
+
236
+ @test norm (exp (Quaternion (0 , 0 , 0 , 0 ))) ≈ 1
237
+ @test norm (exp (Quaternion (2 , 0 , 0 , 0 ))) ≠ 1
238
+ @test norm (exp (Quaternion (0 , 2 , 0 , 0 ))) ≈ 1
239
+ @test norm (exp (Quaternion (0 , 0 , 2 , 0 ))) ≈ 1
240
+ @test norm (exp (Quaternion (0 , 0 , 0 , 2 ))) ≈ 1
241
+
242
+ @test exp (Quaternion (0. , 0. , 0. , 0. )) === Quaternion (1. , 0. , 0. , 0. , true )
243
+ @test exp (Quaternion (2. , 0. , 0. , 0. )) === Quaternion (exp (2 ), 0 , 0 , 0 , false )
244
+ @test exp (Quaternion (0. , 2. , 0. , 0. )) === Quaternion (cos (2 ), sin (2 ), 0 , 0 , true )
245
+ @test exp (Quaternion (0. , 0. , 2. , 0. )) === Quaternion (cos (2 ), 0 , sin (2 ), 0 , true )
246
+ @test exp (Quaternion (0. , 0. , 0. , 2. )) === Quaternion (cos (2 ), 0 , 0 , sin (2 ), true )
247
+
248
+ @test norm (exp (Quaternion (0. , 0. , 0. , 0. ))) ≈ 1
249
+ @test norm (exp (Quaternion (2. , 0. , 0. , 0. ))) ≠ 1
250
+ @test norm (exp (Quaternion (0. , 2. , 0. , 0. ))) ≈ 1
251
+ @test norm (exp (Quaternion (0. , 0. , 2. , 0. ))) ≈ 1
252
+ @test norm (exp (Quaternion (0. , 0. , 0. , 2. ))) ≈ 1
253
+
254
+ @test exp (Quaternion (0 ,0 ,0 ,0 )) isa Quaternion{Float64}
255
+ @test exp (Quaternion (0. ,0 ,0 ,0 )) isa Quaternion{Float64}
256
+ @test exp (Quaternion (0 // 1 ,0 ,0 ,0 )) isa Quaternion{Float64}
257
+ @test exp (Quaternion (BigFloat (0 ),0 ,0 ,0 )) isa Quaternion{BigFloat}
258
+
259
+ # https://github.com/JuliaGeometry/Quaternions.jl/issues/39
260
+ @testset " exp(::Quaternion{Int})" begin
261
+ @test exp (Quaternion (1 ,1 ,1 ,1 )) ≈ exp (Quaternion (1.0 ,1.0 ,1.0 ,1.0 ))
262
+ end
263
+ end
264
+ end
265
+ end
266
+
267
+ @testset " ^" begin
268
+ @testset " ^(::Quaternion, ::Real)" begin
269
+ for _ in 1 : 100
270
+ q = randn (QuaternionF64)
271
+ @test q^ 2.0 ≈ q * q
272
+ @test q^ 1.0 ≈ q
273
+ @test q^- 1.0 ≈ inv (q)
274
+ @test q^ 1.3 ≈ exp (1.3 * log (q))
275
+ @test q^ 7.8 ≈ exp (7.8 * log (q))
276
+ @test q^ 1.3f0 ≈ exp (1.3f0 * log (q))
277
+ @test q^ 7.8f0 ≈ exp (7.8f0 * log (q))
278
+ end
279
+ end
280
+ @testset " ^(::Quaternion, ::Quaternion)" begin
281
+ @test Quaternion (ℯ,0 ,0 ,0 )^ Quaternion (0 ,0 ,π/ 2 ,0 ) ≈ Quaternion (0 ,0 ,1 ,0 )
282
+ @test Quaternion (3.5 ,0 ,0 ,2.3 )^ Quaternion (0.2 ,0 ,0 ,1.7 ) ≈
283
+ Quaternion (real ((3.5 + 2.3im )^ (0.2 + 1.7im )),0 ,0 ,imag ((3.5 + 2.3im )^ (0.2 + 1.7im )))
284
+ for _ in 1 : 100
285
+ q, p = randn (QuaternionF64, 2 )
286
+ @test q^ p ≈ exp (p * log (q))
287
+ end
288
+ end
289
+ end
290
+
291
+ for _ in 1 : 100
175
292
let # test qrotation and angleaxis inverse
176
293
ax = randn (3 ); ax = ax / norm (ax)
177
294
Θ = π * rand ()
@@ -230,37 +347,6 @@ for _ in 1:100
230
347
end
231
348
end
232
349
233
- @testset " exp" begin
234
- @test exp (Quaternion (0 , 0 , 0 , 0 )) === Quaternion (1. , 0. , 0. , 0. , true )
235
- @test exp (Quaternion (2 , 0 , 0 , 0 )) === Quaternion (exp (2 ), 0 , 0 , 0 , false )
236
- @test exp (Quaternion (0 , 2 , 0 , 0 )) === Quaternion (cos (2 ), sin (2 ), 0 , 0 , true )
237
- @test exp (Quaternion (0 , 0 , 2 , 0 )) === Quaternion (cos (2 ), 0 , sin (2 ), 0 , true )
238
- @test exp (Quaternion (0 , 0 , 0 , 2 )) === Quaternion (cos (2 ), 0 , 0 , sin (2 ), true )
239
-
240
- @test norm (exp (Quaternion (0 , 0 , 0 , 0 ))) ≈ 1
241
- @test norm (exp (Quaternion (2 , 0 , 0 , 0 ))) ≠ 1
242
- @test norm (exp (Quaternion (0 , 2 , 0 , 0 ))) ≈ 1
243
- @test norm (exp (Quaternion (0 , 0 , 2 , 0 ))) ≈ 1
244
- @test norm (exp (Quaternion (0 , 0 , 0 , 2 ))) ≈ 1
245
-
246
- @test exp (Quaternion (0. , 0. , 0. , 0. )) === Quaternion (1. , 0. , 0. , 0. , true )
247
- @test exp (Quaternion (2. , 0. , 0. , 0. )) === Quaternion (exp (2 ), 0 , 0 , 0 , false )
248
- @test exp (Quaternion (0. , 2. , 0. , 0. )) === Quaternion (cos (2 ), sin (2 ), 0 , 0 , true )
249
- @test exp (Quaternion (0. , 0. , 2. , 0. )) === Quaternion (cos (2 ), 0 , sin (2 ), 0 , true )
250
- @test exp (Quaternion (0. , 0. , 0. , 2. )) === Quaternion (cos (2 ), 0 , 0 , sin (2 ), true )
251
-
252
- @test norm (exp (Quaternion (0. , 0. , 0. , 0. ))) ≈ 1
253
- @test norm (exp (Quaternion (2. , 0. , 0. , 0. ))) ≠ 1
254
- @test norm (exp (Quaternion (0. , 2. , 0. , 0. ))) ≈ 1
255
- @test norm (exp (Quaternion (0. , 0. , 2. , 0. ))) ≈ 1
256
- @test norm (exp (Quaternion (0. , 0. , 0. , 2. ))) ≈ 1
257
-
258
- @test exp (Quaternion (0 ,0 ,0 ,0 )) isa Quaternion{Float64}
259
- @test exp (Quaternion (0. ,0 ,0 ,0 )) isa Quaternion{Float64}
260
- @test exp (Quaternion (0 // 1 ,0 ,0 ,0 )) isa Quaternion{Float64}
261
- @test exp (Quaternion (BigFloat (0 ),0 ,0 ,0 )) isa Quaternion{BigFloat}
262
- end
263
-
264
350
@testset " random quaternions" begin
265
351
@testset " quatrand" begin
266
352
rng = Random. MersenneTwister (42 )
0 commit comments