Author: mattip <matti.pi...@gmail.com>
Branch: object-dtype2
Changeset: r76695:f8e674fa7afc
Date: 2015-04-03 00:23 +0300
http://bitbucket.org/pypy/pypy/changeset/f8e674fa7afc/

Log:    add many ufuncs

diff --git a/pypy/module/micronumpy/test/test_ufuncs.py 
b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -397,7 +397,7 @@
         for i in range(3):
             assert min_c_b[i] == min(b[i], c)
 
-    def test_scalar(self):
+    def test_all_available(self):
         # tests that by calling all available ufuncs on scalars, none will
         # raise uncaught interp-level exceptions, (and crash the test)
         # and those that are uncallable can be accounted for.
@@ -412,6 +412,8 @@
                 if isinstance(u, np.ufunc):
                     try:
                         u(* [array] * u.nin)
+                    except AttributeError:
+                        pass
                     except TypeError:
                         assert s not in uncallable
                         uncallable.add(s)
@@ -427,7 +429,9 @@
                  'fabs', 'fmod', 'invert', 'mod',
                  'logaddexp', 'logaddexp2', 'left_shift', 'right_shift',
                  'copysign', 'signbit', 'ceil', 'floor', 'trunc'])
-        assert find_uncallable_ufuncs('object') == set()
+        assert find_uncallable_ufuncs('object') == set(
+                ['isnan', 'logaddexp2', 'copysign', 'isfinite', 'signbit',
+                 'isinf', 'logaddexp'])
 
     def test_int_only(self):
         from numpy import bitwise_and, array
diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py
--- a/pypy/module/micronumpy/types.py
+++ b/pypy/module/micronumpy/types.py
@@ -149,7 +149,9 @@
         return self.box(array[0])
 
     def unbox(self, box):
-        assert isinstance(box, self.BoxType)
+        if not isinstance(box, self.BoxType):
+            # i.e. box is an ObjectBox
+            raise oefmt(self.space.w_AttributeError, '')
         return box.value
 
     def coerce(self, space, dtype, w_item):
@@ -427,29 +429,25 @@
     def default_fromstring(self, space):
         return self.box(0)
 
-    @specialize.argtype(1, 2)
-    def div(self, b1, b2):
-        v1 = self.for_computation(self.unbox(b1))
-        v2 = self.for_computation(self.unbox(b2))
+    @simple_binary_op
+    def div(self, v1, v2):
         if v2 == 0:
-            return self.box(0)
+            return 0
         if (self.T is rffi.SIGNEDCHAR or self.T is rffi.SHORT or self.T is 
rffi.INT or
                 self.T is rffi.LONG or self.T is rffi.LONGLONG):
             if v2 == -1 and v1 == 
self.for_computation(most_neg_value_of(self.T)):
-                return self.box(0)
-        return self.box(v1 / v2)
+                return 0
+        return v1 / v2
 
-    @specialize.argtype(1, 2)
-    def floordiv(self, b1, b2):
-        v1 = self.for_computation(self.unbox(b1))
-        v2 = self.for_computation(self.unbox(b2))
+    @simple_binary_op
+    def floordiv(self, v1, v2):
         if v2 == 0:
-            return self.box(0)
+            return 0
         if (self.T is rffi.SIGNEDCHAR or self.T is rffi.SHORT or self.T is 
rffi.INT or
                 self.T is rffi.LONG or self.T is rffi.LONGLONG):
             if v2 == -1 and v1 == 
self.for_computation(most_neg_value_of(self.T)):
-                return self.box(0)
-        return self.box(v1 // v2)
+                return 0
+        return v1 // v2
 
     @simple_binary_op
     def mod(self, v1, v2):
@@ -485,7 +483,7 @@
         elif v < 0:
             return -1
         else:
-            assert v == 0
+            #assert v == 0
             return 0
 
     @raw_unary_op
@@ -1711,16 +1709,134 @@
     def for_computation(v):
         return v
 
-    @simple_binary_op
-    def add(self, v1, v2):
-        return v1
-        #return self.space.add(v1, v2)
+    @raw_binary_op
+    def eq(self, v1, v2):
+        return self.space.eq_w(v1, v2)
 
     @raw_binary_op
-    def eq(self, v1, v2):
-        return True
-        #return self.space.eq_w(v1, v2)
+    def max(self, v1, v2):
+        if self.space.is_true(self.space.ge(v1, v2)):
+            return v1
+        return v2
 
+    @raw_binary_op
+    def min(self, v1, v2):
+        if self.space.is_true(self.space.le(v1, v2)):
+            return v1
+        return v2
+
+    def arctan2(self, v1, v2):
+        raise oefmt(self.space.w_AttributeError, 'arctan2')
+
+    @specialize.argtype(1)
+    def _bool(self, v):
+        return self.space.bool_w(v)
+
+    @raw_binary_op
+    def logical_and(self, v1, v2):
+        return self._bool(v1) and self._bool(v2)
+
+    @raw_binary_op
+    def logical_or(self, v1, v2):
+        return self._bool(v1) or self._bool(v2)
+
+    @raw_unary_op
+    def logical_not(self, v):
+        return not self._bool(v)
+
+    @raw_binary_op
+    def logical_xor(self, v1, v2):
+        a = self._bool(v1)
+        b = self._bool(v2)
+        return (not b and a) or (not a and b)
+
+    @simple_binary_op
+    def bitwise_and(self, v1, v2):
+        return self.space.and_(v1, v2)
+
+    @simple_binary_op
+    def bitwise_or(self, v1, v2):
+        return self.space.or_(v1, v2)
+
+    @simple_binary_op
+    def bitwise_xor(self, v1, v2):
+        return self.space.xor(v1, v2)
+
+    @simple_binary_op
+    def pow(self, v1, v2):
+        return self.space.pow(v1, v2, self.space.wrap(1))
+
+    @simple_unary_op
+    def reciprocal(self, v1):
+        return self.space.div(self.space.wrap(1.0), v1)
+
+    @simple_unary_op
+    def sign(self, v):
+        zero = self.space.wrap(0)
+        one = self.space.wrap(1)
+        m_one = self.space.wrap(-1)
+        if self.space.is_true(self.space.gt(v, zero)):
+            return one
+        elif self.space.is_true(self.space.lt(v, zero)):
+            return m_one
+        else:
+            return zero
+
+
+def add_unsupported_op(cls, op):
+    def func(self, *args):
+        raise oefmt(self.space.w_TypeError, 
+            "ufunc '%s' not supported for input types", op)
+    func.__name__ = 'object_' + op
+    setattr(cls, op, func)
+        
+
+def add_unary_op(cls, op):
+    @simple_unary_op
+    def func(self, w_v):
+        w_impl = self.space.lookup(w_v, op)
+        if w_impl is None:
+            raise oefmt(self.space.w_AttributeError, op)
+        return self.space.get_and_call_function(w_impl, w_v)
+    func.__name__ = 'object_' + op
+    setattr(cls, op, func)
+
+def add_space_unary_op(cls, op):
+    @simple_unary_op
+    def func(self, v):
+        return getattr(self.space, op)(v)
+    func.__name__ = 'object_' + op
+    setattr(cls, op, func)
+
+def add_space_binary_op(cls, op):
+    @simple_binary_op
+    def func(self, v1, v2):
+        return getattr(self.space, op)(v1, v2)
+    func.__name__ = 'object_' + op
+    setattr(cls, op, func)
+
+def add_space_comp_op(cls, op):
+    @raw_binary_op
+    def func(self, v1, v2):
+        return self.space.is_true(getattr(self.space, op)(v1, v2))
+    func.__name__ = 'object_' + op
+    setattr(cls, op, func)
+
+for op in ('copysign', 'isfinite', 'isinf', 'isnan', 'logaddexp', 'logaddexp2',
+           'signbit',):
+    add_unsupported_op(ObjectType, op)
+for op in ('conj', 'real', 'imag', 'rint'):
+    add_unary_op(ObjectType, op)
+for op in ('abs', 'neg', 'pos', 'invert'):
+    add_space_unary_op(ObjectType, op)
+for op in ('add', 'floordiv', 'div', 'mod', 'mul', 'sub', 'lshift', 'rshift'):
+    add_space_binary_op(ObjectType, op)
+for op in ('lt', 'gt', 'le', 'ge', 'ne'):
+    add_space_comp_op(ObjectType, op)
+
+ObjectType.fmax = ObjectType.max
+ObjectType.fmin = ObjectType.min
+ObjectType.fmod = ObjectType.mod
 
 class FlexibleType(BaseType):
     def get_element_size(self):
diff --git a/pypy/module/micronumpy/ufuncs.py b/pypy/module/micronumpy/ufuncs.py
--- a/pypy/module/micronumpy/ufuncs.py
+++ b/pypy/module/micronumpy/ufuncs.py
@@ -349,7 +349,7 @@
         if dtype.is_flexible():
             raise OperationError(space.w_TypeError,
                       space.wrap('Not implemented for this type'))
-        if (self.int_only and not dtype.is_int() or
+        if (self.int_only and not (dtype.is_int() or dtype.is_object()) or
                 not self.allow_bool and dtype.is_bool() or
                 not self.allow_complex and dtype.is_complex()):
             raise oefmt(space.w_TypeError,
@@ -465,9 +465,9 @@
             w_ldtype, w_rdtype,
             promote_to_float=self.promote_to_float,
             promote_bools=self.promote_bools)
-        if (self.int_only and (not w_ldtype.is_int() or
-                               not w_rdtype.is_int() or
-                               not calc_dtype.is_int()) or
+        if (self.int_only and (not (w_ldtype.is_int() or w_ldtype.is_object()) 
or
+                               not (w_rdtype.is_int() or w_rdtype.is_object()) 
or
+                               not (calc_dtype.is_int() or 
calc_dtype.is_object())) or
                 not self.allow_bool and (w_ldtype.is_bool() or
                                          w_rdtype.is_bool()) or
                 not self.allow_complex and (w_ldtype.is_complex() or
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to