[pypy-commit] pypy py3k: Implement sys.hash_info. Initial patch by chronitis, thanks!

amauryfa noreply at buildbot.pypy.org
Wed Nov 23 00:18:48 CET 2011


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3k
Changeset: r49675:aa1d34b5a927
Date: 2011-11-23 00:10 +0100
http://bitbucket.org/pypy/pypy/changeset/aa1d34b5a927/

Log:	Implement sys.hash_info. Initial patch by chronitis, thanks!

diff --git a/pypy/module/sys/__init__.py b/pypy/module/sys/__init__.py
--- a/pypy/module/sys/__init__.py
+++ b/pypy/module/sys/__init__.py
@@ -78,6 +78,7 @@
 
         'float_info'            : 'system.get_float_info(space)',
         'int_info'              : 'system.get_int_info(space)',
+        'hash_info'             : 'system.get_hash_info(space)',
         'float_repr_style'      : 'system.get_float_repr_style(space)'
         }
 
diff --git a/pypy/module/sys/system.py b/pypy/module/sys/system.py
--- a/pypy/module/sys/system.py
+++ b/pypy/module/sys/system.py
@@ -1,8 +1,8 @@
 """Information about the current system."""
 from pypy.interpreter import gateway
 from pypy.rlib import rfloat, rbigint
-from pypy.rpython.lltypesystem import rffi
-
+from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.rlib.objectmodel import HASH_INF, HASH_NAN, HASH_IMAG
 
 app = gateway.applevel("""
 "NOT_RPYTHON"
@@ -24,6 +24,13 @@
 class int_info(metaclass=structseqtype):
     bits_per_digit = structseqfield(0)
     sizeof_digit = structseqfield(1)
+    
+class hash_info(metaclass=structseqtype):
+    width = structseqfield(0)
+    modulus = structseqfield(1)
+    inf = structseqfield(2)
+    nan = structseqfield(3)
+    imag = structseqfield(4)
 """)
 
 
@@ -55,6 +62,19 @@
     w_int_info = app.wget(space, "int_info")
     return space.call_function(w_int_info, space.newtuple(info_w))
 
+def get_hash_info(space):
+    # XXX our _hash_float() always give values that fit in 32bit
+    modulus = (1 << 31) - 1  # Must be a prime number
+    info_w = [
+        space.wrap(8 * rffi.sizeof(lltype.Signed)),
+        space.wrap(modulus),
+        space.wrap(HASH_INF),
+        space.wrap(HASH_NAN),
+        space.wrap(HASH_IMAG),
+    ]
+    w_hash_info = app.wget(space, "hash_info")
+    return space.call_function(w_hash_info, space.newtuple(info_w))
+
 def get_float_repr_style(space):
     if rfloat.USE_SHORT_FLOAT_REPR:
         return space.wrap("short")
diff --git a/pypy/module/sys/test/test_sysmodule.py b/pypy/module/sys/test/test_sysmodule.py
--- a/pypy/module/sys/test/test_sysmodule.py
+++ b/pypy/module/sys/test/test_sysmodule.py
@@ -127,6 +127,18 @@
         assert isinstance(li.bits_per_digit, int)
         assert isinstance(li.sizeof_digit, int)
 
+    def test_hash_info(self):
+        import sys
+        li = sys.hash_info
+        assert isinstance(li.width, int)
+        assert isinstance(li.modulus, int)
+        assert isinstance(li.inf, int)
+        assert isinstance(li.nan, int)
+        assert isinstance(li.imag, int)
+        print(li)
+        sys.stdout.flush()
+        assert 0
+
 class AppTestSysModulePortedFromCPython:
 
     def setup_class(cls):
diff --git a/pypy/objspace/std/complexobject.py b/pypy/objspace/std/complexobject.py
--- a/pypy/objspace/std/complexobject.py
+++ b/pypy/objspace/std/complexobject.py
@@ -7,6 +7,7 @@
 from pypy.objspace.std.longobject import W_LongObject
 from pypy.rlib.rfloat import (
     formatd, DTSF_STR_PRECISION, isinf, isnan, copysign)
+from pypy.rlib.objectmodel import HASH_IMAG
 
 import math
 
@@ -127,7 +128,7 @@
 def hash__Complex(space, w_value):
     hashreal = _hash_float(space, w_value.realval)
     hashimg = _hash_float(space, w_value.imagval)
-    combined = hashreal + 1000003 * hashimg
+    combined = hashreal + HASH_IMAG * hashimg
     return space.newint(combined)
 
 def add__Complex_Complex(space, w_complex1, w_complex2):
diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py
--- a/pypy/objspace/std/floatobject.py
+++ b/pypy/objspace/std/floatobject.py
@@ -14,6 +14,7 @@
     DTSF_ADD_DOT_0, DTSF_STR_PRECISION)
 from pypy.rlib.rbigint import rbigint
 from pypy.rlib.objectmodel import we_are_translated
+from pypy.rlib.objectmodel import HASH_INF, HASH_NAN
 from pypy.rlib import rfloat
 from pypy.tool.sourcetools import func_with_new_name
 
@@ -272,7 +273,7 @@
     from pypy.objspace.std.longobject import hash__Long
 
     if isnan(v):
-        return 0
+        return HASH_NAN
 
     # This is designed so that Python numbers of different types
     # that compare equal hash to the same value; otherwise comparisons
@@ -292,9 +293,9 @@
             except OverflowError:
                 # can't convert to long int -- arbitrary
                 if v < 0:
-                    return -271828
+                    return -HASH_INF
                 else:
-                    return 314159
+                    return HASH_INF
             return space.int_w(space.hash(w_lval))
 
     # The fractional part is non-zero, so we don't have to worry about
diff --git a/pypy/objspace/std/test/test_floatobject.py b/pypy/objspace/std/test/test_floatobject.py
--- a/pypy/objspace/std/test/test_floatobject.py
+++ b/pypy/objspace/std/test/test_floatobject.py
@@ -104,7 +104,7 @@
         # testing special overflow values
         inf = 1e200 * 1e200
         assert hash(inf) == 314159
-        assert hash(-inf) == -271828
+        assert hash(-inf) == -314159
         assert hash(inf/inf) == 0
 
     def test_int_float(self):
diff --git a/pypy/rlib/objectmodel.py b/pypy/rlib/objectmodel.py
--- a/pypy/rlib/objectmodel.py
+++ b/pypy/rlib/objectmodel.py
@@ -321,6 +321,10 @@
     x ^= length
     return intmask(x)
 
+HASH_INF  = 314159
+HASH_NAN  = 0
+HASH_IMAG = 1000003
+
 def _hash_float(f):
     """The algorithm behind compute_hash() for a float.
     This implementation is identical to the CPython implementation,
@@ -332,11 +336,11 @@
     if not isfinite(f):
         if isinf(f):
             if f < 0.0:
-                return -271828
+                return -HASH_INF
             else:
-                return 314159
+                return HASH_INF
         else: #isnan(f):
-            return 0
+            return HASH_NAN
     v, expo = math.frexp(f)
     v *= TAKE_NEXT
     hipart = int(v)


More information about the pypy-commit mailing list