|
59 | 59 | @test Quaternion(1, 2, 3, 4) != Quaternion(1, 2, 3, 5)
|
60 | 60 | end
|
61 | 61 |
|
| 62 | + @testset "isequal" begin |
| 63 | + @test isequal(Quaternion(1, 2, 3, 4), Quaternion(1.0, 2.0, 3.0, 4.0)) |
| 64 | + @test !isequal(Quaternion(1, 2, 3, 4), Quaternion(5, 2, 3, 4)) |
| 65 | + @test isequal(Quaternion(NaN, -0.0, Inf, -Inf), Quaternion(NaN, -0.0, Inf, -Inf)) |
| 66 | + @test !isequal(Quaternion(NaN, 0.0, Inf, -Inf), Quaternion(NaN, -0.0, Inf, -Inf)) |
| 67 | + end |
| 68 | + |
62 | 69 | @testset "convert" begin
|
63 | 70 | @test convert(Quaternion{Float64}, 1) === Quaternion(1.0)
|
64 | 71 | @test convert(Quaternion{Float64}, Quaternion(1, 2, 3, 4)) ===
|
|
153 | 160 | @test conj(conj(q)) === q
|
154 | 161 | @test conj(conj(qnorm)) === qnorm
|
155 | 162 | @test float(Quaternion(1, 2, 3, 4)) === float(Quaternion(1.0, 2.0, 3.0, 4.0))
|
156 |
| - @test Quaternions.abs_imag(q) == abs(Quaternion(0, q.v1, q.v2, q.v3)) |
| 163 | + @test Quaternions.abs_imag(q) ≈ abs(Quaternion(0, q.v1, q.v2, q.v3)) |
| 164 | + end |
| 165 | + |
| 166 | + @testset "abs/abs_imag don't over/underflow" begin |
| 167 | + for x in [1e-300, 1e300, -1e-300, -1e300] |
| 168 | + @test abs(quat(x, 0, 0, 0)) == abs(x) |
| 169 | + @test abs(quat(0, x, 0, 0)) == abs(x) |
| 170 | + @test abs(quat(0, 0, x, 0)) == abs(x) |
| 171 | + @test abs(quat(0, 0, 0, x)) == abs(x) |
| 172 | + @test Quaternions.abs_imag(quat(0, x, 0, 0)) == abs(x) |
| 173 | + @test Quaternions.abs_imag(quat(0, 0, x, 0)) == abs(x) |
| 174 | + @test Quaternions.abs_imag(quat(0, 0, 0, x)) == abs(x) |
| 175 | + end |
| 176 | + @test isnan(abs(quat(NaN, NaN, NaN, NaN))) |
| 177 | + @test abs(quat(NaN, Inf, NaN, NaN)) == Inf |
| 178 | + @test abs(quat(-Inf, NaN, NaN, NaN)) == Inf |
| 179 | + @test abs(quat(0.0)) == 0.0 |
| 180 | + @test abs(quat(Inf)) == Inf |
| 181 | + @test abs(quat(1, -Inf, 2, 3)) == Inf |
| 182 | + @test isnan(Quaternions.abs_imag(quat(0, NaN, NaN, NaN))) |
| 183 | + @test Quaternions.abs_imag(quat(0, Inf, NaN, NaN)) == Inf |
| 184 | + @test Quaternions.abs_imag(quat(0, NaN, -Inf, NaN)) == Inf |
| 185 | + @test Quaternions.abs_imag(quat(0.0)) == 0.0 |
| 186 | + @test Quaternions.abs_imag(quat(0.0, 0.0, Inf, 0.0)) == Inf |
| 187 | + @test Quaternions.abs_imag(quat(0, 1, -Inf, 2)) == Inf |
157 | 188 | end
|
158 | 189 |
|
159 | 190 | @testset "algebraic properties" begin
|
|
171 | 202 | end
|
172 | 203 | end
|
173 | 204 |
|
| 205 | + @testset "inv does not under/overflow" begin |
| 206 | + x = 1e-300 |
| 207 | + y = inv(x) |
| 208 | + @test isequal(inv(quat(x, 0.0, 0.0, 0.0)), quat(y, -0.0, -0.0, -0.0)) |
| 209 | + @test isequal(inv(quat(0.0, x, 0.0, 0.0)), quat(0.0, -y, -0.0, -0.0)) |
| 210 | + @test isequal(inv(quat(0.0, 0.0, x, 0.0)), quat(0.0, -0.0, -y, -0.0)) |
| 211 | + @test isequal(inv(quat(0.0, 0.0, 0.0, x)), quat(0.0, -0.0, -0.0, -y)) |
| 212 | + @test isequal(inv(quat(y, 0.0, 0.0, 0.0)), quat(x, -0.0, -0.0, -0.0)) |
| 213 | + @test isequal(inv(quat(0.0, y, 0.0, 0.0)), quat(0.0, -x, -0.0, -0.0)) |
| 214 | + @test isequal(inv(quat(0.0, 0.0, y, 0.0)), quat(0.0, -0.0, -x, -0.0)) |
| 215 | + @test isequal(inv(quat(0.0, 0.0, 0.0, y)), quat(0.0, -0.0, -0.0, -x)) |
| 216 | + @test isequal(inv(quat(-Inf, 1, -2, 3)), quat(-0.0, -0.0, 0.0, -0.0)) |
| 217 | + @test isequal(inv(quat(1, -2, Inf, 3)), quat(0.0, 0.0, -0.0, -0.0)) |
| 218 | + end |
| 219 | + |
174 | 220 | @testset "isreal" begin
|
175 | 221 | @test isreal(Quaternion(1, 0, 0, 0))
|
176 | 222 | @test !isreal(Quaternion(2, 1, 0, 0))
|
|
275 | 321 | @test q2 \ q ≈ inv(q2) * q
|
276 | 322 | @test q / x ≈ x \ q ≈ inv(x) * q
|
277 | 323 | end
|
| 324 | + @testset "no overflow/underflow" begin |
| 325 | + @testset for x in [1e-300, 1e300, -1e-300, -1e300] |
| 326 | + @test quat(x) / quat(x) == quat(1) |
| 327 | + @test quat(x) / quat(0, x, 0, 0) == quat(0, -1, 0, 0) |
| 328 | + @test quat(x) / quat(0, 0, x, 0) == quat(0, 0, -1, 0) |
| 329 | + @test quat(x) / quat(0, 0, 0, x) == quat(0, 0, 0, -1) |
| 330 | + @test quat(0, x, 0, 0) / quat(x, 0, 0, 0) == quat(0, 1, 0, 0) |
| 331 | + @test quat(0, x, 0, 0) / quat(0, x, 0, 0) == quat(1, 0, 0, 0) |
| 332 | + @test quat(0, x, 0, 0) / quat(0, 0, x, 0) == quat(0, 0, 0, -1) |
| 333 | + @test quat(0, x, 0, 0) / quat(0, 0, 0, x) == quat(0, 0, 1, 0) |
| 334 | + end |
| 335 | + @testset for T in [Float32, Float64] |
| 336 | + o = one(T) |
| 337 | + z = zero(T) |
| 338 | + inf = T(Inf) |
| 339 | + nan = T(NaN) |
| 340 | + @testset for s in [1, -1], t in [1, -1] |
| 341 | + @test isequal(quat(o) / quat(s*inf), quat(s*z, -z, -z, -z)) |
| 342 | + @test isequal(quat(o) / quat(s*inf, t*o, z, t*z), quat(s*z, -t*z, -z, -t*z)) |
| 343 | + @test isequal(quat(o) / quat(s*inf, t*nan, t*z, z), quat(s*z, nan, -t*z, -z)) |
| 344 | + @test isequal(quat(o) / quat(s*inf, t*inf, t*z, z), quat(s*z, -t*z, -t*z, -z)) |
| 345 | + end |
| 346 | + @test isequal(quat(inf) / quat(inf, 1, 2, 3), quat(nan, nan, nan, nan)) |
| 347 | + @test isequal(quat(inf) / quat(inf, 1, 2, -inf), quat(nan, nan, nan, nan)) |
| 348 | + end |
| 349 | + end |
278 | 350 | end
|
279 | 351 |
|
280 | 352 | @testset "^" begin
|
|
0 commit comments