Author: Antonio Cuni <[email protected]>
Branch: faster-rstruct
Changeset: r80669:b790b4f590e3
Date: 2015-11-13 17:18 +0100
http://bitbucket.org/pypy/pypy/changeset/b790b4f590e3/

Log:    use the fast raw_storage way to read doubles and floats when rstruct
        is using native formats

diff --git a/rpython/rlib/rawstorage.py b/rpython/rlib/rawstorage.py
--- a/rpython/rlib/rawstorage.py
+++ b/rpython/rlib/rawstorage.py
@@ -45,6 +45,7 @@
 
 
 @rgc.no_collect
[email protected]()
 def str_storage_getitem(TP, s, index):
     lls = llstr(s)
     # from here, no GC operations can happen
@@ -56,6 +57,7 @@
     return res
 
 @rgc.no_collect
[email protected]()
 def str_storage_getitem_unaligned(TP, s, index):
     lls = llstr(s)
     # from here, no GC operations can happen
diff --git a/rpython/rlib/rstruct/nativefmttable.py 
b/rpython/rlib/rstruct/nativefmttable.py
--- a/rpython/rlib/rstruct/nativefmttable.py
+++ b/rpython/rlib/rstruct/nativefmttable.py
@@ -10,6 +10,7 @@
 from rpython.rlib.rstruct import standardfmttable as std
 from rpython.rlib.rstruct.error import StructError
 from rpython.rlib.unroll import unrolling_iterable
+from rpython.rlib.rawstorage import str_storage_getitem
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.rtyper.tool import rffi_platform
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
@@ -27,9 +28,6 @@
 # ____________________________________________________________
 
 
-double_buf = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw', immortal=True)
-float_buf = lltype.malloc(rffi.FLOATP.TO, 1, flavor='raw', immortal=True)
-
 range_8_unroll = unrolling_iterable(list(reversed(range(8))))
 range_4_unroll = unrolling_iterable(list(reversed(range(4))))
 
@@ -48,10 +46,7 @@
 @specialize.argtype(0)
 def unpack_double(fmtiter):
     input = fmtiter.read(sizeof_double)
-    p = rffi.cast(rffi.CCHARP, double_buf)
-    for i in range(sizeof_double):
-        p[i] = input[i]
-    doubleval = double_buf[0]
+    doubleval = str_storage_getitem(rffi.DOUBLE, input, 0)
     fmtiter.appendobj(doubleval)
 
 def pack_float(fmtiter):
@@ -71,11 +66,8 @@
 @specialize.argtype(0)
 def unpack_float(fmtiter):
     input = fmtiter.read(sizeof_float)
-    p = rffi.cast(rffi.CCHARP, float_buf)
-    for i in range(sizeof_float):
-        p[i] = input[i]
-    floatval = float_buf[0]
-    doubleval = float(floatval)
+    floatval = str_storage_getitem(rffi.FLOAT, input, 0)
+    doubleval = float(floatval) # convert from r_singlefloat to rpython's float
     fmtiter.appendobj(doubleval)
 
 # ____________________________________________________________
diff --git a/rpython/rlib/rstruct/test/test_runpack.py 
b/rpython/rlib/rstruct/test/test_runpack.py
--- a/rpython/rlib/rstruct/test/test_runpack.py
+++ b/rpython/rlib/rstruct/test/test_runpack.py
@@ -37,3 +37,21 @@
             return runpack(">d", "testtest")
         assert fn() == struct.unpack(">d", "testtest")[0]
         assert self.interpret(fn, []) == struct.unpack(">d", "testtest")[0]
+
+    def test_native_floats(self):
+        """
+        Check the 'd' and 'f' format characters on native packing.
+        """
+        d_data = struct.pack("d", 12.34)
+        f_data = struct.pack("f", 12.34)
+        def fn():
+            d = runpack("@d", d_data)
+            f = runpack("@f", f_data)
+            return d, f
+        #
+        res = self.interpret(fn, [])
+        d = res.item0
+        f = res.item1  # convert from r_singlefloat
+        assert d == 12.34     # no precision lost
+        assert f != 12.34     # precision lost
+        assert abs(f - 12.34) < 1E-6
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to