[pypy-commit] pypy longdouble: preliminary implementation of long double

rlamy noreply at buildbot.pypy.org
Wed Mar 20 21:02:03 CET 2013


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: longdouble
Changeset: r62553:e5b66e73b23e
Date: 2013-03-20 20:00 +0000
http://bitbucket.org/pypy/pypy/changeset/e5b66e73b23e/

Log:	preliminary implementation of long double

diff --git a/rpython/annotator/binaryop.py b/rpython/annotator/binaryop.py
--- a/rpython/annotator/binaryop.py
+++ b/rpython/annotator/binaryop.py
@@ -131,7 +131,7 @@
     def is_((obj1, obj2)):
         r = SomeBool()
         if obj2.is_constant():
-            if obj1.is_constant(): 
+            if obj1.is_constant():
                 r.const = obj1.const is obj2.const
             if obj2.const is None and not obj1.can_be_none():
                 r.const = False
@@ -149,7 +149,7 @@
 
             def bind(src_obj, tgt_obj, tgt_arg):
                 if hasattr(tgt_obj, 'is_type_of') and src_obj.is_constant():
-                    add_knowntypedata(knowntypedata, True, tgt_obj.is_type_of, 
+                    add_knowntypedata(knowntypedata, True, tgt_obj.is_type_of,
                                       bk.valueoftype(src_obj.const))
 
                 assert annotator.binding(op.args[tgt_arg]) == tgt_obj
@@ -175,7 +175,7 @@
         getbookkeeper().count("coerce", obj1, obj2)
         return pair(obj1, obj2).union()   # reasonable enough
 
-    # approximation of an annotation intersection, the result should be the annotation obj or 
+    # approximation of an annotation intersection, the result should be the annotation obj or
     # the intersection of obj and improvement
     def improve((obj, improvement)):
         if not improvement.contains(obj) and obj.contains(improvement):
@@ -322,7 +322,7 @@
             return int0.knowntype
         if int1.nonneg and isinstance(op.args[1], Variable):
             case = opname in ('lt', 'le', 'eq')
-                
+
             add_knowntypedata(knowntypedata, case, [op.args[1]],
                               SomeInteger(nonneg=True, knowntype=tointtype(int2)))
         if int2.nonneg and isinstance(op.args[0], Variable):
@@ -333,7 +333,7 @@
         # a special case for 'x < 0' or 'x >= 0',
         # where 0 is a flow graph Constant
         # (in this case we are sure that it cannot become a r_uint later)
-        if (isinstance(op.args[1], Constant) and 
+        if (isinstance(op.args[1], Constant) and
             type(op.args[1].value) is int and    # filter out Symbolics
             op.args[1].value == 0):
             if int1.nonneg:
@@ -354,14 +354,14 @@
 class __extend__(pairtype(SomeBool, SomeBool)):
 
     def union((boo1, boo2)):
-        s = SomeBool() 
-        if getattr(boo1, 'const', -1) == getattr(boo2, 'const', -2): 
-            s.const = boo1.const 
+        s = SomeBool()
+        if getattr(boo1, 'const', -1) == getattr(boo2, 'const', -2):
+            s.const = boo1.const
         if hasattr(boo1, 'knowntypedata') and \
            hasattr(boo2, 'knowntypedata'):
             ktd = merge_knowntypedata(boo1.knowntypedata, boo2.knowntypedata)
             s.set_knowntypedata(ktd)
-        return s 
+        return s
 
     def and_((boo1, boo2)):
         s = SomeBool()
@@ -386,13 +386,13 @@
             if boo2.const:
                 s.const = True
         return s
-        
+
     def xor((boo1, boo2)):
         s = SomeBool()
         if boo1.is_constant() and boo2.is_constant():
             s.const = boo1.const ^ boo2.const
         return s
-        
+
 class __extend__(pairtype(SomeString, SomeString)):
 
     def union((str1, str2)):
@@ -495,7 +495,7 @@
         return s_string.__class__()
 
 class __extend__(pairtype(SomeFloat, SomeFloat)):
-    
+
     def union((flt1, flt2)):
         return SomeFloat()
 
@@ -512,16 +512,26 @@
 
 
 class __extend__(pairtype(SomeSingleFloat, SomeSingleFloat)):
-    
+
     def union((flt1, flt2)):
         return SomeSingleFloat()
 
 
 class __extend__(pairtype(SomeLongFloat, SomeLongFloat)):
-    
+
     def union((flt1, flt2)):
         return SomeLongFloat()
 
+    add = sub = mul = union
+
+    def div((flt1, flt2)):
+        return SomeLongFloat()
+    div.can_only_throw = []
+    truediv = div
+
+    # repeat these in order to copy the 'can_only_throw' attribute
+    inplace_div = div
+    inplace_truediv = truediv
 
 class __extend__(pairtype(SomeList, SomeList)):
 
@@ -610,7 +620,7 @@
 
 
 class __extend__(pairtype(SomeTuple, SomeInteger)):
-    
+
     def getitem((tup1, int2)):
         if int2.is_immutable_constant():
             try:
@@ -624,7 +634,7 @@
 
 
 class __extend__(pairtype(SomeList, SomeInteger)):
-    
+
     def mul((lst1, int2)):
         return lst1.listdef.offspring()
 
@@ -643,27 +653,27 @@
     getitem_idx_key = getitem_idx
 
     def setitem((lst1, int2), s_value):
-        getbookkeeper().count("list_setitem", int2)        
+        getbookkeeper().count("list_setitem", int2)
         lst1.listdef.mutate()
         lst1.listdef.generalize(s_value)
     setitem.can_only_throw = [IndexError]
 
     def delitem((lst1, int2)):
-        getbookkeeper().count("list_delitem", int2)        
+        getbookkeeper().count("list_delitem", int2)
         lst1.listdef.resize()
     delitem.can_only_throw = [IndexError]
 
 class __extend__(pairtype(SomeString, SomeInteger)):
 
     def getitem((str1, int2)):
-        getbookkeeper().count("str_getitem", int2)        
+        getbookkeeper().count("str_getitem", int2)
         return SomeChar(no_nul=str1.no_nul)
     getitem.can_only_throw = []
 
     getitem_key = getitem
 
     def getitem_idx((str1, int2)):
-        getbookkeeper().count("str_getitem", int2)        
+        getbookkeeper().count("str_getitem", int2)
         return SomeChar(no_nul=str1.no_nul)
     getitem_idx.can_only_throw = [IndexError]
 
@@ -675,14 +685,14 @@
 
 class __extend__(pairtype(SomeUnicodeString, SomeInteger)):
     def getitem((str1, int2)):
-        getbookkeeper().count("str_getitem", int2)        
+        getbookkeeper().count("str_getitem", int2)
         return SomeUnicodeCodePoint()
     getitem.can_only_throw = []
 
     getitem_key = getitem
 
     def getitem_idx((str1, int2)):
-        getbookkeeper().count("str_getitem", int2)        
+        getbookkeeper().count("str_getitem", int2)
         return SomeUnicodeCodePoint()
     getitem_idx.can_only_throw = [IndexError]
 
@@ -694,7 +704,7 @@
 
 class __extend__(pairtype(SomeInteger, SomeString),
                  pairtype(SomeInteger, SomeUnicodeString)):
-    
+
     def mul((int1, str2)): # xxx do we want to support this
         getbookkeeper().count("str_mul", str2, int1)
         return str2.basestringclass()
@@ -714,7 +724,7 @@
         return result
 
 class __extend__(pairtype(SomeInteger, SomeList)):
-    
+
     def mul((int1, lst2)):
         return lst2.listdef.offspring()
 
@@ -787,7 +797,7 @@
 
 class __extend__(pairtype(SomePBC, SomePBC)):
 
-    def union((pbc1, pbc2)):       
+    def union((pbc1, pbc2)):
         d = pbc1.descriptions.copy()
         d.update(pbc2.descriptions)
         return SomePBC(d, can_be_None = pbc1.can_be_None or pbc2.can_be_None)
diff --git a/rpython/annotator/test/test_annrpython.py b/rpython/annotator/test/test_annrpython.py
--- a/rpython/annotator/test/test_annrpython.py
+++ b/rpython/annotator/test/test_annrpython.py
@@ -10,8 +10,8 @@
 from rpython.annotator.listdef import ListDef, ListChangeUnallowed
 from rpython.annotator.dictdef import DictDef
 from rpython.flowspace.model import *
-from rpython.rlib.rarithmetic import r_uint, base_int, r_longlong, r_ulonglong
-from rpython.rlib.rarithmetic import r_singlefloat
+from rpython.rlib.rarithmetic import (r_uint, base_int, r_longlong,
+        r_ulonglong, r_singlefloat, r_longfloat)
 from rpython.rlib import objectmodel
 from rpython.flowspace.objspace import build_flow, FlowingError
 
@@ -3263,6 +3263,17 @@
         s = a.build_types(g, [int])
         assert isinstance(s, annmodel.SomeSingleFloat)
 
+    def test_r_longfloat(self):
+        z = r_longfloat(0.4)
+        def g(n):
+            if n > 0:
+                return r_longfloat(n * 0.1)
+            else:
+                return z
+        a = self.RPythonAnnotator()
+        s = a.build_types(g, [int])
+        assert isinstance(s, annmodel.SomeLongFloat)
+
     def test_unicode_simple(self):
         def f():
             return u'xxx'
diff --git a/rpython/annotator/test/test_model.py b/rpython/annotator/test/test_model.py
--- a/rpython/annotator/test/test_model.py
+++ b/rpython/annotator/test/test_model.py
@@ -56,11 +56,11 @@
                                                      (s6, s6)])
 
 def test_commonbase_simple():
-    class A0: 
+    class A0:
         pass
-    class A1(A0): 
+    class A1(A0):
         pass
-    class A2(A0): 
+    class A2(A0):
         pass
     class B1(object):
         pass
@@ -72,10 +72,10 @@
     except TypeError:    # if A0 is also a new-style class, e.g. in PyPy
         class B3(A0, object):
             pass
-    assert commonbase(A1,A2) is A0 
+    assert commonbase(A1,A2) is A0
     assert commonbase(A1,A0) is A0
     assert commonbase(A1,A1) is A1
-    assert commonbase(A2,B2) is object 
+    assert commonbase(A2,B2) is object
     assert commonbase(A2,B3) is A0
 
 def test_list_union():
@@ -124,8 +124,8 @@
     s_pos = SomeInteger(nonneg=True)
     s_1 = SomeInteger(nonneg=True); s_1.const = 1
     s_m1 = SomeInteger(nonneg=False); s_m1.const = -1
-    s_u = SomeInteger(nonneg=True, unsigned=True); 
-    s_u1 = SomeInteger(nonneg=True, unsigned=True); 
+    s_u = SomeInteger(nonneg=True, unsigned=True);
+    s_u1 = SomeInteger(nonneg=True, unsigned=True);
     s_u1.const = r_uint(1)
     assert annotation_to_lltype(s_i) == lltype.Signed
     assert annotation_to_lltype(s_pos) == lltype.Signed
@@ -145,7 +145,10 @@
     s_singlefloat = SomeSingleFloat()
     s_singlefloat.const = r_singlefloat(0.0)
     assert annotation_to_lltype(s_singlefloat) == lltype.SingleFloat
-    
+    s_longfloat = SomeLongFloat()
+    s_longfloat.const = r_longfloat(0.0)
+    assert annotation_to_lltype(s_longfloat) == lltype.LongFloat
+
 def test_ll_union():
     PS1 = lltype.Ptr(lltype.GcStruct('s'))
     PS2 = lltype.Ptr(lltype.GcStruct('s'))
diff --git a/rpython/rlib/rarithmetic.py b/rpython/rlib/rarithmetic.py
--- a/rpython/rlib/rarithmetic.py
+++ b/rpython/rlib/rarithmetic.py
@@ -611,6 +611,28 @@
         return hop.genop('cast_primitive', [v],
                          resulttype = lltype.SingleFloat)
 
+class For_r_longfloat_values_Entry(extregistry.ExtRegistryEntry):
+    _type_ = r_longfloat
+
+    def compute_annotation(self):
+        from rpython.annotator import model as annmodel
+        return annmodel.SomeLongFloat()
+
+class For_r_longfloat_type_Entry(extregistry.ExtRegistryEntry):
+    _about_ = r_longfloat
+
+    def compute_result_annotation(self, *args_s, **kwds_s):
+        from rpython.annotator import model as annmodel
+        return annmodel.SomeLongFloat()
+
+    def specialize_call(self, hop):
+        from rpython.rtyper.lltypesystem import lltype
+        v, = hop.inputargs(lltype.Float)
+        hop.exception_cannot_occur()
+        # we use cast_primitive to go between Float and LongFloat.
+        return hop.genop('cast_primitive', [v],
+                         resulttype = lltype.LongFloat)
+
 
 def int_between(n, m, p):
     """ check that n <= m < p. This assumes that n <= p. This is useful because
diff --git a/rpython/rtyper/rfloat.py b/rpython/rtyper/rfloat.py
--- a/rpython/rtyper/rfloat.py
+++ b/rpython/rtyper/rfloat.py
@@ -226,3 +226,18 @@
         # we use cast_primitive to go between Float and LongFloat.
         return hop.genop('cast_primitive', [v],
                          resulttype = lltype.Float)
+
+class __extend__(pairtype(LongFloatRepr, LongFloatRepr)):
+
+    #Arithmetic
+
+    def rtype_add(_, hop):
+        return _rtype_template_long(hop, 'add')
+
+    rtype_inplace_add = rtype_add
+
+
+def _rtype_template_long(hop, func):
+    vlist = hop.inputargs(lltype.LongFloat, lltype.LongFloat)
+    return hop.genop('float_'+func, vlist, resulttype=lltype.LongFloat)
+


More information about the pypy-commit mailing list