@@ -862,15 +862,15 @@ def _cmp(self, other):
862862 # that specified by IEEE 754.
863863
864864 def __eq__ (self , other , context = None ):
865- other = _convert_other (other , allow_float = True )
865+ other = _convert_other (other , allow_float = True )
866866 if other is NotImplemented :
867867 return other
868868 if self ._check_nans (other , context ):
869869 return False
870870 return self ._cmp (other ) == 0
871871
872872 def __ne__ (self , other , context = None ):
873- other = _convert_other (other , allow_float = True )
873+ other = _convert_other (other , allow_float = True )
874874 if other is NotImplemented :
875875 return other
876876 if self ._check_nans (other , context ):
@@ -879,7 +879,7 @@ def __ne__(self, other, context=None):
879879
880880
881881 def __lt__ (self , other , context = None ):
882- other = _convert_other (other , allow_float = True )
882+ other = _convert_other (other , allow_float = True )
883883 if other is NotImplemented :
884884 return other
885885 ans = self ._compare_check_nans (other , context )
@@ -888,7 +888,7 @@ def __lt__(self, other, context=None):
888888 return self ._cmp (other ) < 0
889889
890890 def __le__ (self , other , context = None ):
891- other = _convert_other (other , allow_float = True )
891+ other = _convert_other (other , allow_float = True )
892892 if other is NotImplemented :
893893 return other
894894 ans = self ._compare_check_nans (other , context )
@@ -897,7 +897,7 @@ def __le__(self, other, context=None):
897897 return self ._cmp (other ) <= 0
898898
899899 def __gt__ (self , other , context = None ):
900- other = _convert_other (other , allow_float = True )
900+ other = _convert_other (other , allow_float = True )
901901 if other is NotImplemented :
902902 return other
903903 ans = self ._compare_check_nans (other , context )
@@ -906,7 +906,7 @@ def __gt__(self, other, context=None):
906906 return self ._cmp (other ) > 0
907907
908908 def __ge__ (self , other , context = None ):
909- other = _convert_other (other , allow_float = True )
909+ other = _convert_other (other , allow_float = True )
910910 if other is NotImplemented :
911911 return other
912912 ans = self ._compare_check_nans (other , context )
@@ -935,55 +935,28 @@ def compare(self, other, context=None):
935935
936936 def __hash__ (self ):
937937 """x.__hash__() <==> hash(x)"""
938- # Decimal integers must hash the same as the ints
939- #
940- # The hash of a nonspecial noninteger Decimal must depend only
941- # on the value of that Decimal, and not on its representation.
942- # For example: hash(Decimal('100E-1')) == hash(Decimal('10')).
943-
944- # Equality comparisons involving signaling nans can raise an
945- # exception; since equality checks are implicitly and
946- # unpredictably used when checking set and dict membership, we
947- # prevent signaling nans from being used as set elements or
948- # dict keys by making __hash__ raise an exception.
938+
939+ # In order to make sure that the hash of a Decimal instance
940+ # agrees with the hash of a numerically equal integer, float
941+ # or Fraction, we follow the rules for numeric hashes outlined
942+ # in the documentation. (See library docs, 'Built-in Types').
949943 if self ._is_special :
950944 if self .is_snan ():
951945 raise TypeError ('Cannot hash a signaling NaN value.' )
952946 elif self .is_nan ():
953- # 0 to match hash(float('nan'))
954- return 0
947+ return _PyHASH_NAN
955948 else :
956- # values chosen to match hash(float('inf')) and
957- # hash(float('-inf')).
958949 if self ._sign :
959- return - 271828
950+ return - _PyHASH_INF
960951 else :
961- return 314159
962-
963- # In Python 2.7, we're allowing comparisons (but not
964- # arithmetic operations) between floats and Decimals; so if
965- # a Decimal instance is exactly representable as a float then
966- # its hash should match that of the float.
967- self_as_float = float (self )
968- if Decimal .from_float (self_as_float ) == self :
969- return hash (self_as_float )
970-
971- if self ._isinteger ():
972- op = _WorkRep (self .to_integral_value ())
973- # to make computation feasible for Decimals with large
974- # exponent, we use the fact that hash(n) == hash(m) for
975- # any two nonzero integers n and m such that (i) n and m
976- # have the same sign, and (ii) n is congruent to m modulo
977- # 2**64-1. So we can replace hash((-1)**s*c*10**e) with
978- # hash((-1)**s*c*pow(10, e, 2**64-1).
979- return hash ((- 1 )** op .sign * op .int * pow (10 , op .exp , 2 ** 64 - 1 ))
980- # The value of a nonzero nonspecial Decimal instance is
981- # faithfully represented by the triple consisting of its sign,
982- # its adjusted exponent, and its coefficient with trailing
983- # zeros removed.
984- return hash ((self ._sign ,
985- self ._exp + len (self ._int ),
986- self ._int .rstrip ('0' )))
952+ return _PyHASH_INF
953+
954+ if self ._exp >= 0 :
955+ exp_hash = pow (10 , self ._exp , _PyHASH_MODULUS )
956+ else :
957+ exp_hash = pow (_PyHASH_10INV , - self ._exp , _PyHASH_MODULUS )
958+ hash_ = int (self ._int ) * exp_hash % _PyHASH_MODULUS
959+ return hash_ if self >= 0 else - hash_
987960
988961 def as_tuple (self ):
989962 """Represents the number as a triple tuple.
@@ -6218,6 +6191,17 @@ def _format_number(is_negative, intpart, fracpart, exp, spec):
62186191# _SignedInfinity[sign] is infinity w/ that sign
62196192_SignedInfinity = (_Infinity , _NegativeInfinity )
62206193
6194+ # Constants related to the hash implementation; hash(x) is based
6195+ # on the reduction of x modulo _PyHASH_MODULUS
6196+ import sys
6197+ _PyHASH_MODULUS = sys .hash_info .modulus
6198+ # hash values to use for positive and negative infinities, and nans
6199+ _PyHASH_INF = sys .hash_info .inf
6200+ _PyHASH_NAN = sys .hash_info .nan
6201+ del sys
6202+
6203+ # _PyHASH_10INV is the inverse of 10 modulo the prime _PyHASH_MODULUS
6204+ _PyHASH_10INV = pow (10 , _PyHASH_MODULUS - 2 , _PyHASH_MODULUS )
62216205
62226206
62236207if __name__ == '__main__' :
0 commit comments