Skip to content

Commit 3f5c5c1

Browse files
authored
Add Base.hash(::Quaternion, ::UInt) (#136)
* add `Base.hash(::Quaternion)` * add tests for `hash` * update hash for more readability * replace `==` with `===` in hash test
1 parent 6d90f17 commit 3f5c5c1

File tree

2 files changed

+21
-0
lines changed

2 files changed

+21
-0
lines changed

src/Quaternion.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,17 @@ function Base.isequal(q::Quaternion, w::Quaternion)
288288
isequal(q.s, w.s) & isequal(q.v1, w.v1) & isequal(q.v2, w.v2) & isequal(q.v3, w.v3)
289289
end
290290

291+
if UInt === UInt64
292+
const h_imags = 0xfa29df508725c1bf, 0x5e6c4b26a400626d, 0x8dfd375bac9f9403
293+
else
294+
const h_imags = 0x62802719, 0x5a9b072e, 0x209019b1
295+
end
296+
const hash_0_imags = hash.(0, h_imags)
297+
298+
function Base.hash(z::Quaternion, h::UInt)
299+
hash(real(z), h xor(xor.(hash.(imag_part(z), h_imags), hash_0_imags)...))
300+
end
301+
291302
"""
292303
extend_analytic(f, q::Quaternion)
293304

test/Quaternion.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,16 @@ end
6666
@test !isequal(Quaternion(NaN, 0.0, Inf, -Inf), Quaternion(NaN, -0.0, Inf, -Inf))
6767
end
6868

69+
@testset "hash" begin
70+
# https://github.com/JuliaGeometry/Quaternions.jl/issues/135
71+
@test hash(0) === hash(quat(0)) === hash(0.0) === hash(quat(0.0))
72+
@test hash(1) === hash(quat(1)) === hash(1.0) === hash(quat(1.0))
73+
@test hash(quat(-0.0)) hash(quat(+0.0))
74+
@test allunique([hash(quat(1,0,0,0)), hash(quat(0,1,0,0)), hash(quat(0,0,1,0)), hash(quat(0,0,0,1))])
75+
@test hash(57, UInt(42)) === hash(quat(57), UInt(42))
76+
@test length(unique(Quaternion[quat(2), quat(big"2")])) == 1
77+
end
78+
6979
@testset "convert" begin
7080
@test convert(Quaternion{Float64}, 1) === Quaternion(1.0)
7181
@test convert(Quaternion{Float64}, Quaternion(1, 2, 3, 4)) ===

0 commit comments

Comments
 (0)