File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 1+
2+ import std/ hashes; export Hash
3+ from ./ isX import isfinite, isinf, isnan
4+ from std/ math import frexp
5+
6+ const PyHASH_BITS* = when sizeof (pointer ) >= 8 : 61 else : 31
7+ const PyHASH_MODULUS* = (1 shl PyHASH_BITS) - 1
8+
9+ const PyHASH_INF* = 314159
10+
11+ type
12+ Py_uhash_t = uint
13+ static : assert sizeof (Py_uhash_t) == sizeof (Hash )
14+
15+
16+ proc Py_HashDouble * (v: float ): Hash =
17+ # # `_Py_HashDouble`
18+ if not isfinite (v):
19+ if isinf (v):
20+ return if v > 0.0 : PyHASH_INF else : - PyHASH_INF
21+ else :
22+ raise newException (ValueError , " cannot hash NaN" )
23+
24+ var (m, e) = frexp (v)
25+
26+ var sign = true
27+ if m < 0.0 :
28+ sign = false
29+ m = - m
30+
31+ var x: Py_uhash_t = 0
32+ var y: Py_uhash_t
33+
34+ while m != 0.0 :
35+ x = ((x shl 28 ) and PyHASH_MODULUS) or (x shr (PyHASH_BITS - 28 ))
36+ m *= 268435456.0 # 2**28
37+ e -= 28
38+ y = Py_uhash_t (m)
39+ m -= float (y)
40+ x += y
41+ if x >= PyHASH_MODULUS:
42+ x -= PyHASH_MODULUS
43+
44+ # adjust for the exponent; first reduce it modulo PyHASH_BITS
45+ e = if e >= 0 :
46+ e mod PyHASH_BITS
47+ else :
48+ PyHASH_BITS - 1 - ((- 1 - e) mod PyHASH_BITS)
49+ x = ((x shl e) and PyHASH_MODULUS) or (x shr (PyHASH_BITS - e))
50+
51+ x = x * Py_uhash_t (sign)
52+ if x == Py_uhash_t.high:
53+ x = cast [Py_uhash_t](- 2 )
54+ return Hash x
55+
56+ proc hash * (v: float ): Hash = Py_HashDouble (v)
You can’t perform that action at this time.
0 commit comments