[pypy-commit] pypy numpy-ufunc-object: refactored ufuncs into objects successfully (well, pending translation). now need to fix test_zjit.

alex_gaynor noreply at buildbot.pypy.org
Tue Aug 30 16:49:05 CEST 2011


Author: Alex Gaynor <alex.gaynor at 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


More information about the pypy-commit mailing list