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