[pypy-svn] r46929 - in pypy/dist/pypy: annotation rlib rlib/test rpython/lltypesystem rpython/lltypesystem/test rpython/test
arigo at codespeak.net
arigo at codespeak.net
Thu Sep 27 11:08:20 CEST 2007
Author: arigo
Date: Thu Sep 27 11:08:18 2007
New Revision: 46929
Modified:
pypy/dist/pypy/annotation/model.py
pypy/dist/pypy/rlib/rarithmetic.py
pypy/dist/pypy/rlib/test/test_rarithmetic.py
pypy/dist/pypy/rpython/lltypesystem/lltype.py
pypy/dist/pypy/rpython/lltypesystem/rffi.py
pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py
pypy/dist/pypy/rpython/test/test_rfloat.py
Log:
Minimal support for single-precision floats in lltype and rarithmetic.
Modified: pypy/dist/pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py (original)
+++ pypy/dist/pypy/annotation/model.py Thu Sep 27 11:08:18 2007
@@ -33,6 +33,7 @@
from pypy.annotation.pairtype import pair, extendabletype
from pypy.tool.tls import tlsobject
from pypy.rlib.rarithmetic import r_uint, r_longlong, r_ulonglong, base_int
+from pypy.rlib.rarithmetic import r_singlefloat
import inspect, weakref
from sys import maxint
from pypy.annotation.description import FunctionDesc
@@ -154,6 +155,15 @@
def can_be_none(self):
return False
+class SomeSingleFloat(SomeObject):
+ "Stands for an r_singlefloat."
+ # No operation supported, not even union with a regular float
+ knowntype = r_singlefloat
+ immutable = True
+
+ def can_be_none(self):
+ return False
+
class SomeInteger(SomeFloat):
"Stands for an object which is known to be an integer."
knowntype = int
@@ -576,6 +586,7 @@
(s_Bool, lltype.Bool),
(SomeInteger(knowntype=r_ulonglong), NUMBER),
(SomeFloat(), lltype.Float),
+ (SomeSingleFloat(), lltype.SingleFloat),
(SomeChar(), lltype.Char),
(SomeUnicodeCodePoint(), lltype.UniChar),
(SomeAddress(), llmemory.Address),
Modified: pypy/dist/pypy/rlib/rarithmetic.py
==============================================================================
--- pypy/dist/pypy/rlib/rarithmetic.py (original)
+++ pypy/dist/pypy/rlib/rarithmetic.py Thu Sep 27 11:08:18 2007
@@ -438,3 +438,77 @@
if x == 0:
x = -1
return intmask(x)
+
+# the 'float' C type
+
+class r_singlefloat(object):
+ """A value of the C type 'float'.
+
+ This is a single-precision floating-point number.
+ Regular 'float' values in Python and RPython are double-precision.
+ Note that we consider this as a black box for now - the only thing
+ you can do with it is cast it back to a regular float."""
+
+ def __init__(self, floatval):
+ import struct
+ # simulates the loss of precision
+ self._bytes = struct.pack("f", floatval)
+
+ def __float__(self):
+ import struct
+ return struct.unpack("f", self._bytes)[0]
+
+ def __nonzero__(self):
+ raise TypeError("not supported on r_singlefloat instances")
+
+ def __cmp__(self, other):
+ raise TypeError("not supported on r_singlefloat instances")
+
+
+class For_r_singlefloat_values_Entry(extregistry.ExtRegistryEntry):
+ _type_ = r_singlefloat
+
+ def compute_annotation(self):
+ return _somesinglefloat()
+
+class For_r_singlefloat_type_Entry(extregistry.ExtRegistryEntry):
+ _about_ = r_singlefloat
+
+ def compute_result_annotation(self, *args_s, **kwds_s):
+ return _somesinglefloat()
+
+ def specialize_call(self, hop):
+ from pypy.rpython.lltypesystem import lltype
+ v, = hop.inputargs(lltype.Float)
+ hop.exception_cannot_occur()
+ # we use cast_primitive to go between Float and SingleFloat.
+ return hop.genop('cast_primitive', [v],
+ resulttype = lltype.SingleFloat)
+
+def _somesinglefloat():
+ """Returns SomeSingleFloat(), but also lazily register the rtyping support
+ for SomeSingleFloat.
+ """
+ from pypy.annotation import model as annmodel
+
+ if 'rtyper_makerepr' not in annmodel.SomeSingleFloat.__dict__:
+ from pypy.rpython.lltypesystem import lltype
+ from pypy.rpython.rmodel import Repr
+
+ class SingleFloatRepr(Repr):
+ lowleveltype = lltype.SingleFloat
+
+ def rtype_float(self, hop):
+ v, = hop.inputargs(lltype.SingleFloat)
+ hop.exception_cannot_occur()
+ # we use cast_primitive to go between Float and SingleFloat.
+ return hop.genop('cast_primitive', [v],
+ resulttype = lltype.Float)
+
+ class __extend__(annmodel.SomeSingleFloat):
+ def rtyper_makerepr(self, rtyper):
+ return SingleFloatRepr()
+ def rtyper_makekey(self):
+ return self.__class__,
+
+ return annmodel.SomeSingleFloat()
Modified: pypy/dist/pypy/rlib/test/test_rarithmetic.py
==============================================================================
--- pypy/dist/pypy/rlib/test/test_rarithmetic.py (original)
+++ pypy/dist/pypy/rlib/test/test_rarithmetic.py Thu Sep 27 11:08:18 2007
@@ -295,6 +295,13 @@
py.test.raises(ValueError, break_up_float, 'e')
+def test_r_singlefloat():
+ x = r_singlefloat(2.5) # exact number
+ assert float(x) == 2.5
+ x = r_singlefloat(2.1) # approximate number, bits are lost
+ assert float(x) != 2.1
+ assert abs(float(x) - 2.1) < 1E-6
+
class BaseTestRarithmetic(BaseRtypingTest):
def test_formatd(self):
from pypy.rlib.rarithmetic import formatd
Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Thu Sep 27 11:08:18 2007
@@ -1,5 +1,5 @@
import py
-from pypy.rlib.rarithmetic import r_int, r_uint, intmask
+from pypy.rlib.rarithmetic import r_int, r_uint, intmask, r_singlefloat
from pypy.rlib.rarithmetic import r_ulonglong, r_longlong, base_int
from pypy.rlib.rarithmetic import normalizedinttype
from pypy.rlib.objectmodel import Symbolic
@@ -584,7 +584,10 @@
SignedLongLong = build_number("SignedLongLong", r_longlong)
UnsignedLongLong = build_number("UnsignedLongLong", r_ulonglong)
-Float = Primitive("Float", 0.0)
+Float = Primitive("Float", 0.0) # C type 'double'
+SingleFloat = Primitive("SingleFloat", r_singlefloat(0.0)) # C type 'float'
+r_singlefloat._TYPE = SingleFloat
+
Char = Primitive("Char", '\x00')
Bool = Primitive("Bool", False)
Void = Primitive("Void", None)
@@ -680,12 +683,16 @@
if ORIG == Char or ORIG == UniChar:
value = ord(value)
elif ORIG == Float:
+ if TGT == SingleFloat:
+ return r_singlefloat(value)
value = long(value)
cast = _to_primitive.get(TGT)
if cast is not None:
return cast(value)
if isinstance(TGT, Number):
return TGT._cast(value)
+ if ORIG == SingleFloat and TGT == Float:
+ return float(value)
raise TypeError, "unsupported cast"
def _cast_whatever(TGT, value):
Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Thu Sep 27 11:08:18 2007
@@ -254,9 +254,13 @@
# (use SIGNEDCHAR or UCHAR for the small integer types)
CHAR = lltype.Char
-# double - XXX there is no support for the C type 'float' in the C backend yet
+# double
DOUBLE = lltype.Float
+# float - corresponds to pypy.rlib.rarithmetic.r_float, and supports no
+# operation except rffi.cast() between FLOAT and DOUBLE
+FLOAT = lltype.SingleFloat
+
# void * - for now, represented as char *
VOIDP = lltype.Ptr(lltype.Array(lltype.Char, hints={'nolength': True}))
Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py Thu Sep 27 11:08:18 2007
@@ -549,6 +549,7 @@
def test_cast_primitive():
cases = [
(Float, 1, 1.0),
+ (Float, r_singlefloat(2.1), float(r_singlefloat(2.1))),
(Signed, 1.0, 1),
(Unsigned, 1.0, 1),
(Signed, r_uint(-1), -1),
@@ -562,6 +563,9 @@
res = cast_primitive(TGT, orig_val)
assert typeOf(res) == TGT
assert res == expect
+ res = cast_primitive(SingleFloat, 2.1)
+ assert isinstance(res, r_singlefloat)
+ assert float(res) == float(r_singlefloat(2.1))
def test_cast_identical_array_ptr_types():
A = GcArray(Signed)
Modified: pypy/dist/pypy/rpython/test/test_rfloat.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rfloat.py (original)
+++ pypy/dist/pypy/rpython/test/test_rfloat.py Thu Sep 27 11:08:18 2007
@@ -2,7 +2,7 @@
from pypy.translator.translator import TranslationContext
from pypy.rpython.test import snippet
from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
-from pypy.rlib.rarithmetic import r_uint, r_longlong
+from pypy.rlib.rarithmetic import r_uint, r_longlong, r_singlefloat
class TestSnippet(object):
@@ -94,6 +94,15 @@
res = self.interpret(fn, [-9])
assert self.float_eq(res, 0.5 * ((sys.maxint+1)*2 - 9))
+ def test_r_singlefloat(self):
+ def fn(x):
+ y = r_singlefloat(x)
+ return float(y)
+
+ res = self.interpret(fn, [2.1])
+ assert res != 2.1 # precision lost
+ assert abs(res - 2.1) < 1E-6
+
def test_float_constant_conversions(self):
DIV = r_longlong(10 ** 10)
def fn():
More information about the Pypy-commit
mailing list