Skip to content

Commit

Permalink
BUG/ENH: Switch to simplified __array_ufunc__/binop interaction
Browse files Browse the repository at this point in the history
As per the discussion at numpygh-5844, and in particular
   numpy#5844 (comment)
this commit switches binop dispatch to mostly defer to ufuncs, except
in some specific cases elaborated in a long comment in number.c.

The basic strategy is to define a single piece of C code that knows
how to handle forward binop overrides, and we put it into
private/binop_override.h so that it can be accessed by both the array
code in multiarray.so and the scalar code in umath.so.
  • Loading branch information
njsmith authored and mherkazandjian committed May 30, 2017
1 parent bcd6997 commit 31e4a04
Show file tree
Hide file tree
Showing 8 changed files with 521 additions and 442 deletions.
45 changes: 10 additions & 35 deletions numpy/core/src/multiarray/arrayobject.c
Expand Up @@ -54,6 +54,8 @@ maintainer email: oliphant.travis@ieee.org
#include "mem_overlap.h"
#include "numpyos.h"

#include "binop_override.h"

/*NUMPY_API
Compute the size of an array (in number of items)
*/
Expand Down Expand Up @@ -1335,23 +1337,12 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)

switch (cmp_op) {
case Py_LT:
if (needs_right_binop_forward(obj_self, other, "__gt__", 0) &&
Py_TYPE(obj_self)->tp_richcompare != Py_TYPE(other)->tp_richcompare) {
/* See discussion in number.c */
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
result = PyArray_GenericBinaryFunction(self, other,
n_ops.less);
RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
result = PyArray_GenericBinaryFunction(self, other, n_ops.less);
break;
case Py_LE:
if (needs_right_binop_forward(obj_self, other, "__ge__", 0) &&
Py_TYPE(obj_self)->tp_richcompare != Py_TYPE(other)->tp_richcompare) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
result = PyArray_GenericBinaryFunction(self, other,
n_ops.less_equal);
RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
result = PyArray_GenericBinaryFunction(self, other, n_ops.less_equal);
break;
case Py_EQ:
/*
Expand Down Expand Up @@ -1401,11 +1392,7 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
return result;
}

if (needs_right_binop_forward(obj_self, other, "__eq__", 0) &&
Py_TYPE(obj_self)->tp_richcompare != Py_TYPE(other)->tp_richcompare) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
result = PyArray_GenericBinaryFunction(self,
(PyObject *)other,
n_ops.equal);
Expand Down Expand Up @@ -1478,11 +1465,7 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
return result;
}

if (needs_right_binop_forward(obj_self, other, "__ne__", 0) &&
Py_TYPE(obj_self)->tp_richcompare != Py_TYPE(other)->tp_richcompare) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
result = PyArray_GenericBinaryFunction(self, (PyObject *)other,
n_ops.not_equal);
if (result == NULL) {
Expand All @@ -1502,20 +1485,12 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
}
break;
case Py_GT:
if (needs_right_binop_forward(obj_self, other, "__lt__", 0) &&
Py_TYPE(obj_self)->tp_richcompare != Py_TYPE(other)->tp_richcompare) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
result = PyArray_GenericBinaryFunction(self, other,
n_ops.greater);
break;
case Py_GE:
if (needs_right_binop_forward(obj_self, other, "__le__", 0) &&
Py_TYPE(obj_self)->tp_richcompare != Py_TYPE(other)->tp_richcompare) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
result = PyArray_GenericBinaryFunction(self, other,
n_ops.greater_equal);
break;
Expand Down

0 comments on commit 31e4a04

Please sign in to comment.