Author: Manuel Jacob
Branch: remove-remaining-smm
Changeset: r69323:9b1c802844d9
Date: 2014-02-24 02:49 +0100
http://bitbucket.org/pypy/pypy/changeset/9b1c802844d9/

Log:    Kill float's comparison SMMs.

diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py
--- a/pypy/objspace/std/floatobject.py
+++ b/pypy/objspace/std/floatobject.py
@@ -17,11 +17,8 @@
     DTSF_ADD_DOT_0, DTSF_STR_PRECISION, float_as_rbigint_ratio)
 from rpython.rlib.rbigint import rbigint
 from rpython.rlib.rstring import ParseStringError
-from rpython.tool.sourcetools import func_with_new_name
 from rpython.rlib.unroll import unrolling_iterable
 
-from pypy.objspace.std.intobject import W_IntObject
-
 
 float_as_integer_ratio = SMM("as_integer_ratio", 1)
 float_is_integer = SMM("is_integer", 1)
@@ -110,6 +107,53 @@
     return _hex_from_char(s[i])
 
 
+def make_compare_func(opname):
+    op = getattr(operator, opname)
+
+    if opname == 'eq' or opname == 'ne':
+        def do_compare_bigint(f1, b2):
+            """f1 is a float.  b2 is a bigint."""
+            if not isfinite(f1) or math.floor(f1) != f1:
+                return opname == 'ne'
+            b1 = rbigint.fromfloat(f1)
+            res = b1.eq(b2)
+            if opname == 'ne':
+                res = not res
+            return res
+    else:
+        def do_compare_bigint(f1, b2):
+            """f1 is a float.  b2 is a bigint."""
+            if not isfinite(f1):
+                return op(f1, 0.0)
+            if opname == 'gt' or opname == 'le':
+                # 'float > long'   <==>  'ceil(float) > long'
+                # 'float <= long'  <==>  'ceil(float) <= long'
+                f1 = math.ceil(f1)
+            else:
+                # 'float < long'   <==>  'floor(float) < long'
+                # 'float >= long'  <==>  'floor(float) >= long'
+                f1 = math.floor(f1)
+            b1 = rbigint.fromfloat(f1)
+            return getattr(b1, opname)(b2)
+
+    def _compare(self, space, w_other):
+        if isinstance(w_other, W_FloatObject):
+            return space.newbool(op(self.floatval, w_other.floatval))
+        if space.isinstance_w(w_other, space.w_int):
+            f1 = self.floatval
+            i2 = w_other.intval
+            f2 = float(i2)
+            if LONG_BIT > 32 and int(f2) != i2:
+                res = do_compare_bigint(f1, rbigint.fromint(i2))
+            else:
+                res = op(f1, f2)
+            return space.newbool(res)
+        if space.isinstance_w(w_other, space.w_long):
+            return space.newbool(do_compare_bigint(self.floatval, w_other.num))
+        return space.w_NotImplemented
+    return _compare
+
+
 class W_FloatObject(W_AbstractFloatObject):
     """This is a implementation of the app-level 'float' type.
     The constructor takes an RPython float as an argument."""
@@ -327,6 +371,13 @@
             return space.w_NotImplemented
         return space.newtuple([self, w_other])
 
+    descr_eq = make_compare_func('eq')
+    descr_ne = make_compare_func('ne')
+    descr_lt = make_compare_func('lt')
+    descr_le = make_compare_func('le')
+    descr_gt = make_compare_func('gt')
+    descr_ge = make_compare_func('ge')
+
     def descr_add(self, space, w_rhs):
         w_rhs = self._to_float(space, w_rhs)
         if w_rhs is None:
@@ -498,6 +549,13 @@
     fromhex = interp2app(W_FloatObject.descr_fromhex, as_classmethod=True),
     __coerce__ = interp2app(W_FloatObject.descr_coerce),
 
+    __eq__ = interp2app(W_FloatObject.descr_eq),
+    __ne__ = interp2app(W_FloatObject.descr_ne),
+    __lt__ = interp2app(W_FloatObject.descr_lt),
+    __le__ = interp2app(W_FloatObject.descr_le),
+    __gt__ = interp2app(W_FloatObject.descr_gt),
+    __ge__ = interp2app(W_FloatObject.descr_ge),
+
     __add__ = interp2app(W_FloatObject.descr_add),
     __radd__ = interp2app(W_FloatObject.descr_radd),
     __sub__ = interp2app(W_FloatObject.descr_sub),
@@ -614,113 +672,6 @@
 def format__Float_ANY(space, w_float, w_spec):
     return newformat.run_formatter(space, w_spec, "format_float", w_float)
 
-# ____________________________________________________________
-# A mess to handle all cases of float comparison without relying
-# on delegation, which can unfortunately loose precision when
-# casting an int or a long to a float.
-
-def list_compare_funcs(declarator):
-    for op in ['lt', 'le', 'eq', 'ne', 'gt', 'ge']:
-        func, name = declarator(op)
-        globals()[name] = func_with_new_name(func, name)
-
-def _reverse(opname):
-    if opname[0] == 'l': return 'g' + opname[1:]
-    elif opname[0] == 'g': return 'l' + opname[1:]
-    else: return opname
-
-
-def declare_compare_bigint(opname):
-    """Return a helper function that implements a float-bigint comparison."""
-    op = getattr(operator, opname)
-    #
-    if opname == 'eq' or opname == 'ne':
-        def do_compare_bigint(f1, b2):
-            """f1 is a float.  b2 is a bigint."""
-            if not isfinite(f1) or math.floor(f1) != f1:
-                return opname == 'ne'
-            b1 = rbigint.fromfloat(f1)
-            res = b1.eq(b2)
-            if opname == 'ne':
-                res = not res
-            return res
-    else:
-        def do_compare_bigint(f1, b2):
-            """f1 is a float.  b2 is a bigint."""
-            if not isfinite(f1):
-                return op(f1, 0.0)
-            if opname == 'gt' or opname == 'le':
-                # 'float > long'   <==>  'ceil(float) > long'
-                # 'float <= long'  <==>  'ceil(float) <= long'
-                f1 = math.ceil(f1)
-            else:
-                # 'float < long'   <==>  'floor(float) < long'
-                # 'float >= long'  <==>  'floor(float) >= long'
-                f1 = math.floor(f1)
-            b1 = rbigint.fromfloat(f1)
-            return getattr(b1, opname)(b2)
-    #
-    return do_compare_bigint, 'compare_bigint_' + opname
-list_compare_funcs(declare_compare_bigint)
-
-
-def declare_cmp_float_float(opname):
-    op = getattr(operator, opname)
-    def f(space, w_float1, w_float2):
-        f1 = w_float1.floatval
-        f2 = w_float2.floatval
-        return space.newbool(op(f1, f2))
-    return f, opname + "__Float_Float"
-list_compare_funcs(declare_cmp_float_float)
-
-def declare_cmp_float_int(opname):
-    op = getattr(operator, opname)
-    compare = globals()['compare_bigint_' + opname]
-    def f(space, w_float1, w_int2):
-        f1 = w_float1.floatval
-        i2 = w_int2.intval
-        f2 = float(i2)
-        if LONG_BIT > 32 and int(f2) != i2:
-            res = compare(f1, rbigint.fromint(i2))
-        else:
-            res = op(f1, f2)
-        return space.newbool(res)
-    return f, opname + "__Float_Int"
-list_compare_funcs(declare_cmp_float_int)
-
-def declare_cmp_float_long(opname):
-    compare = globals()['compare_bigint_' + opname]
-    def f(space, w_float1, w_long2):
-        f1 = w_float1.floatval
-        b2 = w_long2.num
-        return space.newbool(compare(f1, b2))
-    return f, opname + "__Float_Long"
-list_compare_funcs(declare_cmp_float_long)
-
-def declare_cmp_int_float(opname):
-    op = getattr(operator, opname)
-    revcompare = globals()['compare_bigint_' + _reverse(opname)]
-    def f(space, w_int1, w_float2):
-        f2 = w_float2.floatval
-        i1 = w_int1.intval
-        f1 = float(i1)
-        if LONG_BIT > 32 and int(f1) != i1:
-            res = revcompare(f2, rbigint.fromint(i1))
-        else:
-            res = op(f1, f2)
-        return space.newbool(res)
-    return f, opname + "__Int_Float"
-list_compare_funcs(declare_cmp_int_float)
-
-def declare_cmp_long_float(opname):
-    revcompare = globals()['compare_bigint_' + _reverse(opname)]
-    def f(space, w_long1, w_float2):
-        f2 = w_float2.floatval
-        b1 = w_long1.num
-        return space.newbool(revcompare(f2, b1))
-    return f, opname + "__Long_Float"
-list_compare_funcs(declare_cmp_long_float)
-
 
 # ____________________________________________________________
 
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to