summaryrefslogtreecommitdiffstats
path: root/Lib/decimal.py
diff options
context:
space:
mode:
authorFacundo Batista <facundobatista@gmail.com>2007-09-19 17:53:25 (GMT)
committerFacundo Batista <facundobatista@gmail.com>2007-09-19 17:53:25 (GMT)
commit8c202440699cef19602acc24822366d0d7c32083 (patch)
treec8dbd3260c57ba194db7aed972a3709da66b6e2c /Lib/decimal.py
parentae406c60180fbaa6d30b82ec2174ea38f9ba746f (diff)
downloadcpython-8c202440699cef19602acc24822366d0d7c32083.zip
cpython-8c202440699cef19602acc24822366d0d7c32083.tar.gz
cpython-8c202440699cef19602acc24822366d0d7c32083.tar.bz2
Issue #1772851. Optimization of __hash__ to behave better for big big
numbers.
Diffstat (limited to 'Lib/decimal.py')
-rw-r--r--Lib/decimal.py15
1 files changed, 11 insertions, 4 deletions
diff --git a/Lib/decimal.py b/Lib/decimal.py
index 4137d06..6ca8bab 100644
--- a/Lib/decimal.py
+++ b/Lib/decimal.py
@@ -766,10 +766,17 @@ class Decimal(object):
if self._isnan():
raise TypeError('Cannot hash a NaN value.')
return hash(str(self))
- i = int(self)
- if self == Decimal(i):
- return hash(i)
- assert self.__nonzero__() # '-0' handled by integer case
+ if not self:
+ return 0
+ if self._isinteger():
+ op = _WorkRep(self.to_integral_value())
+ # to make computation feasible for Decimals with large
+ # exponent, we use the fact that hash(n) == hash(m) for
+ # any two nonzero integers n and m such that (i) n and m
+ # have the same sign, and (ii) n is congruent to m modulo
+ # 2**64-1. So we can replace hash((-1)**s*c*10**e) with
+ # hash((-1)**s*c*pow(10, e, 2**64-1).
+ return hash((-1)**op.sign*op.int*pow(10, op.exp, 2**64-1))
return hash(str(self.normalize()))
def as_tuple(self):