@@ -862,15 +862,15 @@ def _cmp(self, other):
862
862
# that specified by IEEE 754.
863
863
864
864
def __eq__ (self , other , context = None ):
865
- other = _convert_other (other , allow_float = True )
865
+ other = _convert_other (other , allow_float = True )
866
866
if other is NotImplemented :
867
867
return other
868
868
if self ._check_nans (other , context ):
869
869
return False
870
870
return self ._cmp (other ) == 0
871
871
872
872
def __ne__ (self , other , context = None ):
873
- other = _convert_other (other , allow_float = True )
873
+ other = _convert_other (other , allow_float = True )
874
874
if other is NotImplemented :
875
875
return other
876
876
if self ._check_nans (other , context ):
@@ -879,7 +879,7 @@ def __ne__(self, other, context=None):
879
879
880
880
881
881
def __lt__ (self , other , context = None ):
882
- other = _convert_other (other , allow_float = True )
882
+ other = _convert_other (other , allow_float = True )
883
883
if other is NotImplemented :
884
884
return other
885
885
ans = self ._compare_check_nans (other , context )
@@ -888,7 +888,7 @@ def __lt__(self, other, context=None):
888
888
return self ._cmp (other ) < 0
889
889
890
890
def __le__ (self , other , context = None ):
891
- other = _convert_other (other , allow_float = True )
891
+ other = _convert_other (other , allow_float = True )
892
892
if other is NotImplemented :
893
893
return other
894
894
ans = self ._compare_check_nans (other , context )
@@ -897,7 +897,7 @@ def __le__(self, other, context=None):
897
897
return self ._cmp (other ) <= 0
898
898
899
899
def __gt__ (self , other , context = None ):
900
- other = _convert_other (other , allow_float = True )
900
+ other = _convert_other (other , allow_float = True )
901
901
if other is NotImplemented :
902
902
return other
903
903
ans = self ._compare_check_nans (other , context )
@@ -906,7 +906,7 @@ def __gt__(self, other, context=None):
906
906
return self ._cmp (other ) > 0
907
907
908
908
def __ge__ (self , other , context = None ):
909
- other = _convert_other (other , allow_float = True )
909
+ other = _convert_other (other , allow_float = True )
910
910
if other is NotImplemented :
911
911
return other
912
912
ans = self ._compare_check_nans (other , context )
@@ -935,55 +935,28 @@ def compare(self, other, context=None):
935
935
936
936
def __hash__ (self ):
937
937
"""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').
949
943
if self ._is_special :
950
944
if self .is_snan ():
951
945
raise TypeError ('Cannot hash a signaling NaN value.' )
952
946
elif self .is_nan ():
953
- # 0 to match hash(float('nan'))
954
- return 0
947
+ return _PyHASH_NAN
955
948
else :
956
- # values chosen to match hash(float('inf')) and
957
- # hash(float('-inf')).
958
949
if self ._sign :
959
- return - 271828
950
+ return - _PyHASH_INF
960
951
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_
987
960
988
961
def as_tuple (self ):
989
962
"""Represents the number as a triple tuple.
@@ -6218,6 +6191,17 @@ def _format_number(is_negative, intpart, fracpart, exp, spec):
6218
6191
# _SignedInfinity[sign] is infinity w/ that sign
6219
6192
_SignedInfinity = (_Infinity , _NegativeInfinity )
6220
6193
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 )
6221
6205
6222
6206
6223
6207
if __name__ == '__main__' :
0 commit comments