@@ -130,9 +130,11 @@ cdef class Fraction:
130
130
"""
131
131
cdef _numerator
132
132
cdef _denominator
133
+ cdef Py_hash_t _hash
133
134
134
135
def __cinit__ (self , numerator = 0 , denominator = None , _normalize = True ):
135
136
cdef Fraction value
137
+ self ._hash = - 1
136
138
if denominator is None :
137
139
if type (numerator) is int or type (numerator) is long :
138
140
self ._numerator = numerator
@@ -508,25 +510,30 @@ cdef class Fraction:
508
510
509
511
def __hash__ (self ):
510
512
""" hash(self)"""
511
-
512
- # XXX since this method is expensive, consider caching the result
513
+ if self ._hash ! = - 1 :
514
+ return self ._hash
513
515
514
516
# In order to make sure that the hash of a Fraction agrees
515
517
# with the hash of a numerically equal integer, float or
516
518
# Decimal instance, we follow the rules for numeric hashes
517
519
# outlined in the documentation. (See library docs, 'Built-in
518
520
# Types').
519
521
522
+ cdef Py_hash_t result
520
523
# dinv is the inverse of self._denominator modulo the prime
521
524
# _PyHASH_MODULUS, or 0 if self._denominator is divisible by
522
525
# _PyHASH_MODULUS.
523
526
dinv = pow (self ._denominator, _PyHASH_MODULUS - 2 , _PyHASH_MODULUS)
524
527
if not dinv:
525
- hash_ = _PyHASH_INF
528
+ result = _PyHASH_INF
526
529
else :
527
- hash_ = abs (self ._numerator) * dinv % _PyHASH_MODULUS
528
- result = hash_ if self >= 0 else - hash_
529
- return - 2 if result == - 1 else result
530
+ result = abs (self ._numerator) * dinv % _PyHASH_MODULUS
531
+ if self ._numerator < 0 :
532
+ result = - result
533
+ if result == - 1 :
534
+ result = - 2
535
+ self ._hash = result
536
+ return result
530
537
531
538
def __richcmp__ (a , b , int op ):
532
539
if op == Py_EQ:
0 commit comments