diff options
author | Raymond Hettinger <rhettinger@users.noreply.github.com> | 2019-08-16 03:58:26 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-08-16 03:58:26 (GMT) |
commit | f3cb68f2e4c3e0c405460f9bb881f5c1db70f535 (patch) | |
tree | a37473112bfc5b94a21f76aa655a3a8a1a2ea9f3 /Lib/fractions.py | |
parent | 69f37bcb28d7cd78255828029f895958b5baf6ff (diff) | |
download | cpython-f3cb68f2e4c3e0c405460f9bb881f5c1db70f535.zip cpython-f3cb68f2e4c3e0c405460f9bb881f5c1db70f535.tar.gz cpython-f3cb68f2e4c3e0c405460f9bb881f5c1db70f535.tar.bz2 |
bpo-37863: Optimize Fraction.__hash__() (#15298)
Diffstat (limited to 'Lib/fractions.py')
-rw-r--r-- | Lib/fractions.py | 26 |
1 files changed, 11 insertions, 15 deletions
diff --git a/Lib/fractions.py b/Lib/fractions.py index e774d58..c922c38 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -556,23 +556,19 @@ class Fraction(numbers.Rational): def __hash__(self): """hash(self)""" - # XXX since this method is expensive, consider caching the result - - # In order to make sure that the hash of a Fraction agrees - # with the hash of a numerically equal integer, float or - # Decimal instance, we follow the rules for numeric hashes - # outlined in the documentation. (See library docs, 'Built-in - # Types'). - - # dinv is the inverse of self._denominator modulo the prime - # _PyHASH_MODULUS, or 0 if self._denominator is divisible by - # _PyHASH_MODULUS. - dinv = pow(self._denominator, _PyHASH_MODULUS - 2, _PyHASH_MODULUS) - if not dinv: + # To make sure that the hash of a Fraction agrees with the hash + # of a numerically equal integer, float or Decimal instance, we + # follow the rules for numeric hashes outlined in the + # documentation. (See library docs, 'Built-in Types'). + + try: + dinv = pow(self._denominator, -1, _PyHASH_MODULUS) + except ValueError: + # ValueError means there is no modular inverse hash_ = _PyHASH_INF else: - hash_ = abs(self._numerator) * dinv % _PyHASH_MODULUS - result = hash_ if self >= 0 else -hash_ + hash_ = hash(abs(self._numerator)) * dinv % _PyHASH_MODULUS + result = hash_ if self._numerator >= 0 else -hash_ return -2 if result == -1 else result def __eq__(a, b): |