Author: mattip <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit