[pypy-commit] pypy numpy-impicit-convert: Simplifying and moving issequence to objspace

snus_mumrik noreply at buildbot.pypy.org
Fri Jul 8 21:52:26 CEST 2011


Author: Ilya Osadchiy <osadchiy.ilya at gmail.com>
Branch: numpy-impicit-convert
Changeset: r45425:6ee97b808423
Date: 2011-07-08 21:13 +0300
http://bitbucket.org/pypy/pypy/changeset/6ee97b808423/

Log:	Simplifying and moving issequence to objspace

diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -925,6 +925,9 @@
                 return self.w_True
         return self.w_False
 
+    def issequence_w(self, w_obj):
+        return (self.findattr(w_obj, self.wrap("__getitem__")) is not None)
+
     def isinstance_w(self, w_obj, w_type):
         return self.is_true(self.isinstance(w_obj, w_type))
 
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
@@ -7,7 +7,6 @@
 from pypy.tool.sourcetools import func_with_new_name
 import math
 
-
 def dummy1(v):
     assert isinstance(v, float)
     return v
@@ -82,23 +81,15 @@
     def _binop_impl(function):
         signature = Signature()
         def impl(self, space, w_other):
+            w_other = convert_to_array(space, w_other)
             new_sig = self.signature.transition(signature)
-            if isinstance(w_other, BaseArray):
-                res = Call2(
-                    function,
-                    self,
-                    w_other,
-                    new_sig.transition(w_other.signature)
-                )
-                w_other.invalidates.append(res)
-            else:
-                w_other = access_as_array(space, w_other)
-                res = Call2(
-                    function,
-                    self,
-                    w_other,
-                    new_sig.transition(w_other.signature)
-                )
+            res = Call2(
+                function,
+                self,
+                w_other,
+                new_sig.transition(w_other.signature)
+            )
+            w_other.invalidates.append(res)
             self.invalidates.append(res)
             return space.wrap(res)
         return func_with_new_name(impl, "binop_%s_impl" % function.__name__)
@@ -143,14 +134,15 @@
             s += concrete.getitem(i)
         return space.wrap(s / size)
 
-def access_as_array (space, w_obj):
-    try:
+def convert_to_array (space, w_obj):
+    if isinstance(w_obj, BaseArray):
+        return w_obj
+    elif space.issequence_w(w_obj):
+        # Convert to array.
+        return new_numarray(space, w_obj)
+    else:
         # If it's a scalar
         return FloatWrapper(space.float_w(w_obj))
-    except OperationError:
-        # Convert to array.
-        # Could we somehow use COW in some cases?
-        return new_numarray(space, w_obj)
 
 class FloatWrapper(BaseArray):
     """
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,26 +1,17 @@
 import math
 
 from pypy.interpreter.gateway import unwrap_spec
-from pypy.module.micronumpy.interp_numarray import BaseArray, Call1, Call2, Signature, access_as_array
+from pypy.module.micronumpy.interp_numarray import BaseArray, Call1, Call2, Signature, convert_to_array
 from pypy.rlib import rfloat
 from pypy.tool.sourcetools import func_with_new_name
 
-def _issequence(space, w_obj):
-    # Copied from cpyext's PySequence_Check
-    """Return True if the object provides sequence protocol, and False otherwise.
-    This function always succeeds."""
-    return (space.findattr(w_obj, space.wrap("__getitem__")) is not None)
-
 def ufunc(func):
     signature = Signature()
     def impl(space, w_obj):
-        if isinstance(w_obj, BaseArray):
-            w_res = Call1(func, w_obj, w_obj.signature.transition(signature))
-            w_obj.invalidates.append(w_res)
-            return w_res
-        elif _issequence(space, w_obj):
-            w_obj_arr = access_as_array(space, w_obj)
+        if space.issequence_w(w_obj):
+            w_obj_arr = convert_to_array(space, w_obj)
             w_res = Call1(func, w_obj_arr, w_obj_arr.signature.transition(signature))
+            w_obj_arr.invalidates.append(w_res)
             return w_res
         else:
             return space.wrap(func(space.float_w(w_obj)))
@@ -29,31 +20,13 @@
 def ufunc2(func):
     signature = Signature()
     def impl(space, w_lhs, w_rhs):
-        lhs_is_array = isinstance(w_lhs, BaseArray)
-        rhs_is_array = isinstance(w_rhs, BaseArray)
-        if lhs_is_array and rhs_is_array:
-            # This is the (most likely) fall-through case in conversion checks
-            # Not sure if making it a special case makes it much faster
-            new_sig = w_lhs.signature.transition(signature).transition(w_rhs.signature)
-            w_res = Call2(func, w_lhs, w_rhs, new_sig)
-            w_lhs.invalidates.append(w_res)
-            w_rhs.invalidates.append(w_res)
-            return w_res
-        elif _issequence(space, w_lhs) or _issequence(space, w_rhs):
-            if lhs_is_array:
-                w_lhs_arr = w_lhs
-            else:
-                w_lhs_arr = access_as_array(space, w_lhs)
-            if rhs_is_array:
-                w_rhs_arr = w_rhs
-            else:
-                w_rhs_arr = access_as_array(space, w_rhs)
+        if space.issequence_w(w_lhs) or space.issequence_w(w_rhs):
+            w_lhs_arr = convert_to_array(space, w_lhs)
+            w_rhs_arr = convert_to_array(space, w_rhs)
             new_sig = w_lhs_arr.signature.transition(signature).transition(w_rhs_arr.signature)
             w_res = Call2(func, w_lhs_arr, w_rhs_arr, new_sig)
-            if lhs_is_array:
-                w_lhs_arr.invalidates.append(w_res)
-            if rhs_is_array:
-                w_rhs_arr.invalidates.append(w_res)
+            w_lhs_arr.invalidates.append(w_res)
+            w_rhs_arr.invalidates.append(w_res)
             return w_res
         else:
             return space.wrap(func(space.float_w(w_lhs), space.float_w(w_rhs)))
diff --git a/pypy/module/micronumpy/test/test_base.py b/pypy/module/micronumpy/test/test_base.py
--- a/pypy/module/micronumpy/test/test_base.py
+++ b/pypy/module/micronumpy/test/test_base.py
@@ -1,12 +1,10 @@
 from pypy.conftest import gettestobjspace
 from pypy.module.micronumpy.interp_numarray import SingleDimArray, FloatWrapper
 
-
 class BaseNumpyAppTest(object):
     def setup_class(cls):
         cls.space = gettestobjspace(usemodules=('micronumpy',))
 
-
 class TestSignature(object):
     def test_binop_signature(self, space):
         ar = SingleDimArray(10)
@@ -26,4 +24,4 @@
 
         v3 = ar.descr_add(space, v1)
         v4 = ar.descr_add(space, v2)
-        assert v3.signature is v4.signature
\ No newline at end of file
+        assert v3.signature is v4.signature
diff --git a/pypy/module/micronumpy/test/test_zjit.py b/pypy/module/micronumpy/test/test_zjit.py
--- a/pypy/module/micronumpy/test/test_zjit.py
+++ b/pypy/module/micronumpy/test/test_zjit.py
@@ -6,7 +6,16 @@
 from pypy.module.micronumpy.compile import numpy_compile
 
 class FakeSpace(object):
-    pass
+    def issequence_w(self, w_obj):
+        # XXX: get_concrete() fails in some tests 
+        # when using `return hasattr(w_obj, "__getitem__")`
+        return True
+
+    def wrap(self, w_obj):
+        return w_obj
+
+    def float_w(self, w_obj):
+        return float(w_obj)
 
 class TestNumpyJIt(LLJitMixin):
     def setup_class(cls):


More information about the pypy-commit mailing list