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