Author: Antonio Cuni <[email protected]>
Branch: faster-rstruct
Changeset: r80814:8f216a415954
Date: 2015-11-21 11:34 +0100
http://bitbucket.org/pypy/pypy/changeset/8f216a415954/

Log:    there is no distinction between native and standard float/double
        formats: the Python struct module requires that the format is
        ieee754 in both cases. However, in case our platform DOES support
        ieee754, we can directly convert the value from the memory. The very
        slow path defined in ieee.py is used only for obscure platforms
        which do not use native ieee754 floats, or in case we require a
        differend endianess

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
@@ -8,8 +8,7 @@
 from rpython.rlib.objectmodel import specialize
 from rpython.rlib.rarithmetic import r_singlefloat, widen
 from rpython.rlib.rstruct import standardfmttable as std
-from rpython.rlib.rstruct.standardfmttable import (native_is_bigendian, 
unpack_fastpath,
-                                                   CannotUnpack)
+from rpython.rlib.rstruct.standardfmttable import native_is_bigendian
 from rpython.rlib.rstruct.error import StructError
 from rpython.rlib.unroll import unrolling_iterable
 from rpython.rlib.strstorage import str_storage_getitem
@@ -43,16 +42,6 @@
             fmtiter.result.append(chr(value & 0xff))
             value >>= 8
 
[email protected](0)
-def unpack_double(fmtiter):
-    try:
-        doubleval = unpack_fastpath(rffi.DOUBLE)(fmtiter)
-    except CannotUnpack:
-        # slow path, take the slice
-        input = fmtiter.read(sizeof_double)
-        doubleval = str_storage_getitem(rffi.DOUBLE, input, 0)
-    #
-    fmtiter.appendobj(doubleval)
 
 def pack_float(fmtiter):
     doubleval = fmtiter.accept_float_arg()
@@ -68,16 +57,6 @@
             fmtiter.result.append(chr(value & 0xff))
             value >>= 8
 
[email protected](0)
-def unpack_float(fmtiter):
-    try:
-        floatval = unpack_fastpath(rffi.FLOAT)(fmtiter)
-    except CannotUnpack:
-        input = fmtiter.read(sizeof_float)
-        floatval = str_storage_getitem(rffi.FLOAT, input, 0)
-    doubleval = float(floatval) # convert from r_singlefloat to rpython's float
-    fmtiter.appendobj(doubleval)
-
 # ____________________________________________________________
 #
 # Use rffi_platform to get the native sizes and alignments from the C compiler
@@ -134,10 +113,10 @@
 
         if fmtchar == 'f':
             pack = pack_float
-            unpack = unpack_float
+            unpack = std.unpack_float
         elif fmtchar == 'd':
             pack = pack_double
-            unpack = unpack_double
+            unpack = std.unpack_double
         elif fmtchar == '?':
             pack = std.pack_bool
             unpack = std.unpack_bool
diff --git a/rpython/rlib/rstruct/standardfmttable.py 
b/rpython/rlib/rstruct/standardfmttable.py
--- a/rpython/rlib/rstruct/standardfmttable.py
+++ b/rpython/rlib/rstruct/standardfmttable.py
@@ -17,6 +17,7 @@
 from rpython.rtyper.lltypesystem import rffi
 
 native_is_bigendian = struct.pack("=i", 1) == struct.pack(">i", 1)
+native_is_ieee754 = float.__getformat__('double').startswith('IEEE')
 
 def pack_pad(fmtiter, count):
     fmtiter.result.append_multiple_char('\x00', count)
@@ -175,12 +176,27 @@
         end = count
     fmtiter.appendobj(data[1:end])
 
-def make_float_unpacker(size):
+def make_ieee_unpacker(TYPE):
     @specialize.argtype(0)
-    def unpacker(fmtiter):
-        data = fmtiter.read(size)
-        fmtiter.appendobj(ieee.unpack_float(data, fmtiter.bigendian))
-    return unpacker
+    def unpack_ieee(fmtiter):
+        size = rffi.sizeof(TYPE)
+        if fmtiter.bigendian != native_is_bigendian or not native_is_ieee754:
+            # fallback to the very slow unpacking code in ieee.py
+            data = fmtiter.read(size)
+            fmtiter.appendobj(ieee.unpack_float(data, fmtiter.bigendian))
+            return
+        try:
+            # fast path
+            val = unpack_fastpath(TYPE)(fmtiter)
+        except CannotUnpack:
+            # slow path, take the slice
+            input = fmtiter.read(size)
+            val = str_storage_getitem(TYPE, input, 0)
+        fmtiter.appendobj(float(val))
+    return unpack_ieee
+
+unpack_double = make_ieee_unpacker(rffi.DOUBLE)
+unpack_float = make_ieee_unpacker(rffi.FLOAT)
 
 # ____________________________________________________________
 
@@ -267,9 +283,9 @@
     'p':{ 'size' : 1, 'pack' : pack_pascal, 'unpack' : unpack_pascal,
           'needcount' : True },
     'f':{ 'size' : 4, 'pack' : make_float_packer(4),
-                    'unpack' : make_float_unpacker(4)},
+                    'unpack' : unpack_float},
     'd':{ 'size' : 8, 'pack' : make_float_packer(8),
-                    'unpack' : make_float_unpacker(8)},
+                    'unpack' : unpack_double},
     '?':{ 'size' : 1, 'pack' : pack_bool, 'unpack' : unpack_bool},
     }
 
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to