Author: Alex Gaynor <alex.gay...@gmail.com> Branch: numpy-ufunc-object Changeset: r46921:2a49d4ebb30e Date: 2011-08-30 10:48 -0400 http://bitbucket.org/pypy/pypy/changeset/2a49d4ebb30e/
Log: refactored ufuncs into objects successfully (well, pending translation). now need to fix test_zjit. diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py --- a/pypy/module/micronumpy/__init__.py +++ b/pypy/module/micronumpy/__init__.py @@ -1,8 +1,7 @@ - from pypy.interpreter.mixedmodule import MixedModule + class Module(MixedModule): - applevel_name = 'numpy' interpleveldefs = { @@ -14,30 +13,33 @@ 'empty': 'interp_numarray.zeros', 'ones': 'interp_numarray.ones', 'fromstring': 'interp_support.fromstring', + } - # ufuncs - 'abs': 'interp_ufuncs.absolute', - 'absolute': 'interp_ufuncs.absolute', - 'add': 'interp_ufuncs.add', - 'copysign': 'interp_ufuncs.copysign', - 'divide': 'interp_ufuncs.divide', - 'exp': 'interp_ufuncs.exp', - 'fabs': 'interp_ufuncs.fabs', - 'floor': 'interp_ufuncs.floor', - 'maximum': 'interp_ufuncs.maximum', - 'minimum': 'interp_ufuncs.minimum', - 'multiply': 'interp_ufuncs.multiply', - 'negative': 'interp_ufuncs.negative', - 'reciprocal': 'interp_ufuncs.reciprocal', - 'sign': 'interp_ufuncs.sign', - 'subtract': 'interp_ufuncs.subtract', - 'sin': 'interp_ufuncs.sin', - 'cos': 'interp_ufuncs.cos', - 'tan': 'interp_ufuncs.tan', - 'arcsin': 'interp_ufuncs.arcsin', - 'arccos': 'interp_ufuncs.arccos', - 'arctan': 'interp_ufuncs.arctan', - } + # ufuncs + for exposed, impl in [ + ("abs", "absolute"), + ("absolute", "absolute"), + ("add", "add"), + ("arccos", "arccos"), + ("arcsin", "arcsin"), + ("arctan", "arctan"), + ("copysign", "copysign"), + ("cos", "cos"), + ("divide", "divide"), + ("exp", "exp"), + ("fabs", "fabs"), + ("floor", "floor"), + ("maximum", "maximum"), + ("minimum", "minimum"), + ("multiply", "multiply"), + ("negative", "negative"), + ("reciprocal", "reciprocal"), + ("sign", "sign"), + ("sin", "sin"), + ("subtract", "subtract"), + ("tan", "tan"), + ]: + interpleveldefs[exposed] = "interp_ufuncs.get(space).%s" % impl appleveldefs = { 'average': 'app_numpy.average', diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py --- a/pypy/module/micronumpy/interp_numarray.py +++ b/pypy/module/micronumpy/interp_numarray.py @@ -53,42 +53,42 @@ i += 1 return arr - def _unaryop_impl(w_ufunc): + def _unaryop_impl(ufunc_name): def impl(self, space): - return w_ufunc(space, self) - return func_with_new_name(impl, "unaryop_%s_impl" % w_ufunc.name) + return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self]) + return func_with_new_name(impl, "unaryop_%s_impl" % ufunc_name) - descr_pos = _unaryop_impl(interp_ufuncs.positive) - descr_neg = _unaryop_impl(interp_ufuncs.negative) - descr_abs = _unaryop_impl(interp_ufuncs.absolute) + descr_pos = _unaryop_impl("positive") + descr_neg = _unaryop_impl("negative") + descr_abs = _unaryop_impl("absolute") - def _binop_impl(w_ufunc): + def _binop_impl(ufunc_name): def impl(self, space, w_other): - return w_ufunc(space, self, w_other) - return func_with_new_name(impl, "binop_%s_impl" % w_ufunc.name) + return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self, w_other]) + return func_with_new_name(impl, "binop_%s_impl" % ufunc_name) - descr_add = _binop_impl(interp_ufuncs.add) - descr_sub = _binop_impl(interp_ufuncs.subtract) - descr_mul = _binop_impl(interp_ufuncs.multiply) - descr_div = _binop_impl(interp_ufuncs.divide) - descr_pow = _binop_impl(interp_ufuncs.power) - descr_mod = _binop_impl(interp_ufuncs.mod) + descr_add = _binop_impl("add") + descr_sub = _binop_impl("subtract") + descr_mul = _binop_impl("multiply") + descr_div = _binop_impl("divide") + descr_pow = _binop_impl("power") + descr_mod = _binop_impl("mod") - def _binop_right_impl(w_ufunc): + def _binop_right_impl(ufunc_name): def impl(self, space, w_other): w_other = scalar_w(space, interp_ufuncs.find_dtype_for_scalar(space, w_other, self.find_dtype()), w_other ) - return w_ufunc(space, w_other, self) - return func_with_new_name(impl, "binop_right_%s_impl" % w_ufunc.name) + return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [w_other, self]) + return func_with_new_name(impl, "binop_right_%s_impl" % ufunc_name) - descr_radd = _binop_right_impl(interp_ufuncs.add) - descr_rsub = _binop_right_impl(interp_ufuncs.subtract) - descr_rmul = _binop_right_impl(interp_ufuncs.multiply) - descr_rdiv = _binop_right_impl(interp_ufuncs.divide) - descr_rpow = _binop_right_impl(interp_ufuncs.power) - descr_rmod = _binop_right_impl(interp_ufuncs.mod) + descr_radd = _binop_right_impl("add") + descr_rsub = _binop_right_impl("subtract") + descr_rmul = _binop_right_impl("multiply") + descr_rdiv = _binop_right_impl("divide") + descr_rpow = _binop_right_impl("power") + descr_rmod = _binop_right_impl("mod") def _reduce_sum_prod_impl(op_name, init): reduce_driver = jit.JitDriver(greens=['signature'], diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py --- a/pypy/module/micronumpy/interp_ufuncs.py +++ b/pypy/module/micronumpy/interp_ufuncs.py @@ -1,6 +1,6 @@ from pypy.interpreter.baseobjspace import Wrappable from pypy.interpreter.gateway import interp2app -from pypy.interpreter.typedef import TypeDef +from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty from pypy.module.micronumpy import interp_dtype, signature from pypy.tool.sourcetools import func_with_new_name @@ -16,76 +16,88 @@ def descr_repr(self, space): return space.wrap("<ufunc '%s'>" % self.name) + def descr_get_identity(self, space): + if self.identity is None: + return space.w_None + return self.identity.wrap(space) + + def descr_call(self, space, __args__): + args_w = __args__.fixedunpack(self.argcount) + return self.call(space, args_w) + class W_Ufunc1(W_Ufunc): + argcount = 1 + def __init__(self, func, name, promote_to_float=False, promote_bools=False, identity=None): W_Ufunc.__init__(self, name, promote_to_float, promote_bools, identity) self.func = func + self.signature = signature.Call1(func) + + def call(self, space, args_w): + from pypy.module.micronumpy.interp_numarray import (Call1, + convert_to_array, Scalar) + + [w_obj] = args_w + w_obj = convert_to_array(space, w_obj) + res_dtype = find_unaryop_result_dtype(space, + w_obj.find_dtype(), + promote_to_float=self.promote_to_float, + promote_bools=self.promote_bools, + ) + if isinstance(w_obj, Scalar): + return self.func(res_dtype, w_obj.value.convert_to(res_dtype)).wrap(space) + + new_sig = signature.Signature.find_sig([self.signature, w_obj.signature]) + w_res = Call1(new_sig, res_dtype, w_obj) + w_obj.add_invalidates(w_res) + return w_res + class W_Ufunc2(W_Ufunc): + argcount = 2 + def __init__(self, func, name, promote_to_float=False, promote_bools=False, identity=None): W_Ufunc.__init__(self, name, promote_to_float, promote_bools, identity) self.func = func + self.signature = signature.Call2(func) -W_Ufunc.typedef = TypeDef("ufunc", - __module__ = "numpy", - - __repr__ = interp2app(W_Ufunc.descr_repr), -) - -def ufunc(func=None, promote_to_float=False, promote_bools=False): - if func is None: - return lambda func: ufunc(func, promote_to_float, promote_bools) - call_sig = signature.Call1(func) - def impl(space, w_obj): - from pypy.module.micronumpy.interp_numarray import (Call1, - convert_to_array, Scalar) - - w_obj = convert_to_array(space, w_obj) - res_dtype = find_unaryop_result_dtype(space, - w_obj.find_dtype(), - promote_to_float=promote_to_float, - promote_bools=promote_bools, - ) - if isinstance(w_obj, Scalar): - return func(res_dtype, w_obj.value.convert_to(res_dtype)).wrap(space) - - new_sig = signature.Signature.find_sig([call_sig, w_obj.signature]) - w_res = Call1(new_sig, res_dtype, w_obj) - w_obj.add_invalidates(w_res) - return w_res - return func_with_new_name(impl, "%s_dispatcher" % func.__name__) - -def ufunc2(func=None, promote_to_float=False, promote_bools=False): - if func is None: - return lambda func: ufunc2(func, promote_to_float, promote_bools) - - call_sig = signature.Call2(func) - def impl(space, w_lhs, w_rhs): + def call(self, space, args_w): from pypy.module.micronumpy.interp_numarray import (Call2, convert_to_array, Scalar) + [w_lhs, w_rhs] = args_w w_lhs = convert_to_array(space, w_lhs) w_rhs = convert_to_array(space, w_rhs) res_dtype = find_binop_result_dtype(space, w_lhs.find_dtype(), w_rhs.find_dtype(), - promote_to_float=promote_to_float, - promote_bools=promote_bools, + promote_to_float=self.promote_to_float, + promote_bools=self.promote_bools, ) if isinstance(w_lhs, Scalar) and isinstance(w_rhs, Scalar): - return func(res_dtype, w_lhs.value, w_rhs.value).wrap(space) + return self.func(res_dtype, w_lhs.value, w_rhs.value).wrap(space) new_sig = signature.Signature.find_sig([ - call_sig, w_lhs.signature, w_rhs.signature + self.signature, w_lhs.signature, w_rhs.signature ]) w_res = Call2(new_sig, res_dtype, w_lhs, w_rhs) w_lhs.add_invalidates(w_res) w_rhs.add_invalidates(w_res) return w_res - return func_with_new_name(impl, "%s_dispatcher" % func.__name__) + + +W_Ufunc.typedef = TypeDef("ufunc", + __module__ = "numpy", + + __call__ = interp2app(W_Ufunc.descr_call), + __repr__ = interp2app(W_Ufunc.descr_repr), + + identity = GetSetProperty(W_Ufunc.descr_get_identity), + nin = interp_attrproperty("argcount", cls=W_Ufunc) +) def find_binop_result_dtype(space, dt1, dt2, promote_to_float=False, promote_bools=False): @@ -140,7 +152,7 @@ return space.fromcache(interp_dtype.W_Float64Dtype) -def ufunc_dtype_caller(ufunc_name, op_name, argcount, **kwargs): +def ufunc_dtype_caller(ufunc_name, op_name, argcount): if argcount == 1: def impl(res_dtype, value): return getattr(res_dtype, op_name)(value) @@ -149,47 +161,56 @@ return getattr(res_dtype, op_name)(lvalue, rvalue) return func_with_new_name(impl, ufunc_name) -for ufunc_def in [ - ("add", "add", 2, {"identity": 0}), - ("subtract", "sub", 2), - ("multiply", "mul", 2), - ("divide", "div", 2, {"promote_bools": True}), - ("mod", "mod", 2, {"promote_bools": True}), - ("power", "pow", 2, {"promote_bools": True}), +class UfuncState(object): + def __init__(self, space): + "NOT_RPYTHON" + for ufunc_def in [ + ("add", "add", 2, {"identity": 0}), + ("subtract", "sub", 2), + ("multiply", "mul", 2, {"identity": 1}), + ("divide", "div", 2, {"promote_bools": True}), + ("mod", "mod", 2, {"promote_bools": True}), + ("power", "pow", 2, {"promote_bools": True}), - ("maximum", "max", 2), - ("minimum", "min", 2), + ("maximum", "max", 2), + ("minimum", "min", 2), - ("copysign", "copysign", 2, {"promote_to_float": True}), + ("copysign", "copysign", 2, {"promote_to_float": True}), - ("positive", "pos", 1), - ("negative", "neg", 1), - ("absolute", "abs", 1), - ("sign", "sign", 1, {"promote_bools": True}), - ("reciprocal", "reciprocal", 1), + ("positive", "pos", 1), + ("negative", "neg", 1), + ("absolute", "abs", 1), + ("sign", "sign", 1, {"promote_bools": True}), + ("reciprocal", "reciprocal", 1), - ("fabs", "fabs", 1, {"promote_to_float": True}), - ("floor", "floor", 1, {"promote_to_float": True}), - ("exp", "exp", 1, {"promote_to_float": True}), + ("fabs", "fabs", 1, {"promote_to_float": True}), + ("floor", "floor", 1, {"promote_to_float": True}), + ("exp", "exp", 1, {"promote_to_float": True}), - ("sin", "sin", 1, {"promote_to_float": True}), - ("cos", "cos", 1, {"promote_to_float": True}), - ("tan", "tan", 1, {"promote_to_float": True}), - ("arcsin", "arcsin", 1, {"promote_to_float": True}), - ("arccos", "arccos", 1, {"promote_to_float": True}), - ("arctan", "arctan", 1, {"promote_to_float": True}), -]: - ufunc_name = ufunc_def[0] - op_name = ufunc_def[1] - argcount = ufunc_def[2] - try: - extra_kwargs = ufunc_def[3] - except IndexError: - extra_kwargs = {} + ("sin", "sin", 1, {"promote_to_float": True}), + ("cos", "cos", 1, {"promote_to_float": True}), + ("tan", "tan", 1, {"promote_to_float": True}), + ("arcsin", "arcsin", 1, {"promote_to_float": True}), + ("arccos", "arccos", 1, {"promote_to_float": True}), + ("arctan", "arctan", 1, {"promote_to_float": True}), + ]: + self.add_ufunc(space, *ufunc_def) - func = ufunc_dtype_caller(ufunc_name, op_name, argcount) - if argcount == 1: - ufunc = W_Ufunc1(func, ufunc_name, **extra_kwargs) - elif argcount == 2: - ufunc = W_Ufunc2(func, ufunc_name, **extra_kwargs) - globals()[ufunc_name] = ufunc + def add_ufunc(self, space, ufunc_name, op_name, argcount, extra_kwargs=None): + if extra_kwargs is None: + extra_kwargs = {} + + identity = extra_kwargs.get("identity") + if identity is not None: + identity = space.fromcache(interp_dtype.W_Int64Dtype).adapt_val(identity) + extra_kwargs["identity"] = identity + + func = ufunc_dtype_caller(ufunc_name, op_name, argcount) + if argcount == 1: + ufunc = W_Ufunc1(func, ufunc_name, **extra_kwargs) + elif argcount == 2: + ufunc = W_Ufunc2(func, ufunc_name, **extra_kwargs) + setattr(self, ufunc_name, ufunc) + +def get(space): + return space.fromcache(UfuncState) \ No newline at end of file _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit