8000 Pull request #20: Port np.array rich compare. · hpyproject/numpy-hpy@f16c6b6 · GitHub
[go: up one dir, main page]

Skip to content

Commit f16c6b6

Browse files
committed
Pull request #20: Port np.array rich compare.
Merge in numpy-hpy from ss/array_richcmp to labs-hpy-port * commit 'f30a6ccadd888bf8b5b412698b9fd3471c94abbc': array_richcompare Convert scalar nb_subtract to HPy
2 parents 9dea3d7 + f30a6cc commit f16c6b6

File tree

5 files changed

+326
-150
lines changed

5 files changed

+326
-150
lines changed

numpy/core/include/numpy/ndarraytypes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1980,6 +1980,10 @@ static inline bool HPyArray_ISOBJECT(HPyContext *ctx, HPy obj) {
19801980
_PyArray_ISX(ctx, obj, OBJECT);
19811981
}
19821982

1983+
static inline bool HPyArray_ISSTRING(HPyContext *ctx, HPy obj) {
1984+
_PyArray_ISX(ctx, obj, STRING);
1985+
}
1986+
19831987
static inline bool HPyArray_ISINTEGER(HPyContext *ctx, HPy obj) {
19841988
_PyArray_ISX(ctx, obj, INTEGER);
19851989
}

numpy/core/src/common/binop_override.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,4 +305,11 @@ hpy_binop_should_defer(HPyContext *ctx, HPy self, HPy other, int inplace)
305305
} \
306306
} while (0)
307307

308+
#define HPY_RICHCMP_GIVE_UP_IF_NEEDED(ctx, m1, m2) \
309+
do { \
310+
if (hpy_binop_should_defer(ctx, m1, m2, 0)) { \
311+
return HPy_Dup(ctx, ctx->h_NotImplemented); \
312+
} \
313+
} while (0)
314+
308315
#endif /* NUMPY_CORE_SRC_COMMON_BINOP_OVERRIDE_H_ */

numpy/core/src/multiarray/arrayobject.c

Lines changed: 146 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,33 +1451,46 @@ _failed_comparison_workaround(PyArrayObject *self, PyObject *other, int cmp_op)
14511451
return NULL;
14521452
}
14531453

1454-
NPY_NO_EXPORT PyObject *
1455-
array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
1454+
HPyDef_SLOT(array_richcompare_def, hpy_array_richcompare, HPy_tp_richcompare);
1455+
1456+
PyObject *array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
14561457
{
1457-
CAPI_WARN("array_richcompare");
1458-
PyArrayObject *array_other;
1459-
PyObject *obj_self = (PyObject *)self;
1460-
PyObject *result = NULL;
1458+
HPyContext *ctx = npy_get_context();
1459+
HPy h_self = HPy_FromPyObject(ctx, (PyObject*)self);
1460+
HPy h_other = HPy_FromPyObject(ctx, (PyObject*)other);
1461+
HPy result = hpy_array_richcompare(ctx, h_self, h_other, (HPy_RichCmpOp) cmp_op);
1462+
HPy_Close(ctx, h_self);
1463+
HPy_Close(ctx, h_other);
1464+
PyObject *res = HPy_AsPyObject(ctx, result);
1465+
HPy_Close(ctx, result);
1466+
return res;
1467+
}
1468+
1469+
NPY_NO_EXPORT HPy
1470+
hpy_array_richcompare(HPyContext *ctx, /*PyArrayObject*/HPy self, HPy other, HPy_RichCmpOp cmp_op)
1471+
{
1472+
HPy result = HPy_NULL;
14611473

14621474
/* Special case for string arrays (which don't and currently can't have
14631475
* ufunc loops defined, so there's no point in trying).
14641476
*/
1465-
if (PyArray_ISSTRING(self)) {
1466-
array_other = (PyArrayObject *)PyArray_FromObject(other,
1467-
NPY_NOTYPE, 0, 0);
1468-
if (array_other == NULL) {
1469-
PyErr_Clear();
1470-
/* Never mind, carry on, see what happens */
1471-
}
1472-
else if (!PyArray_ISSTRING(array_other)) {
1473-
Py_DECREF(array_other);
1474-
/* Never mind, carry on, see what happens */
1475-
}
1476-
else {
1477-
result = _strings_richcompare(self, array_other, cmp_op, 0);
1478-
Py_DECREF(array_other);
1479-
return result;
1480-
}
1477+
if (HPyArray_ISSTRING(ctx, self)) {
1478+
hpy_abort_not_implemented("string arrays in rich compare");
1479+
// array_other = (PyArrayObject *)PyArray_FromObject(other,
1480+
// NPY_NOTYPE, 0, 0);
1481+
// if (array_other == NULL) {
1482+
// PyErr_Clear();
1483+
// /* Never mind, carry on, see what happens */
1484+
// }
1485+
// else if (!PyArray_ISSTRING(array_other)) {
1486+
// Py_DECREF(array_other);
1487+
// /* Never mind, carry on, see what happens */
1488+
// }
1489+
// else {
1490+
// result = _strings_richcompare(self, array_other, cmp_op, 0);
1491+
// Py_DECREF(array_other);
1492+
// return result;
1493+
// }
14811494
/* If we reach this point, it means that we are not comparing
14821495
* string-to-string. It's possible that this will still work out,
14831496
* e.g. if the other array is an object array, then both will be cast
@@ -1491,140 +1504,141 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
14911504

14921505
switch (cmp_op) {
14931506
case Py_LT:
1494-
RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
1495-
result = PyArray_GenericBinaryFunction(
1496-
(PyObject *)self, other, N_OPS_GET(less));
1507+
HPY_RICHCMP_GIVE_UP_IF_NEEDED(ctx, self, other);
1508+
result = HPyArray_GenericBinaryFunction(
1509+
ctx, self, other, hpy_n_ops.less);
14971510
break;
14981511
case Py_LE:
1499-
RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
1500-
result = PyArray_GenericBinaryFunction(
1501-
(PyObject *)self, other, N_OPS_GET(less_equal));
1512+
HPY_RICHCMP_GIVE_UP_IF_NEEDED(ctx, self, other);
1513+
result = HPyArray_GenericBinaryFunction(
1514+
ctx, self, other, hpy_n_ops.less_equal);
15021515
break;
15031516
case Py_EQ:
1504-
RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
1517+
HPY_RICHCMP_GIVE_UP_IF_NEEDED(ctx, self, other);
15051518
/*
15061519
* The ufunc does not support void/structured types, so these
15071520
* need to be handled specifically. Only a few cases are supported.
15081521
*/
15091522

1510-
if (PyArray_TYPE(self) == NPY_VOID) {
1511-
int _res;
1512-
1513-
array_other = (PyArrayObject *)PyArray_FROM_O(other);
1514-
/*
1515-
* If not successful, indicate that the items cannot be compared
1516-
* this way.
1517-
*/
1518-
if (array_other == NULL) {
1519-
/* 2015-05-07, 1.10 */
1520-
if (DEPRECATE_silence_error(
1521-
"elementwise == comparison failed and returning scalar "
1522-
"instead; this will raise an error in the future.") < 0) {
1523-
return NULL;
1524-
}
1525-
Py_INCREF(Py_NotImplemented);
1526-
return Py_NotImplemented;
1527-
}
1528-
1529-
_res = PyArray_CheckCastSafety(
1530-
NPY_EQUIV_CASTING,
1531-
PyArray_DESCR(self), PyArray_DESCR(array_other), NULL);
1532-
if (_res < 0) {
1533-
PyErr_Clear();
1534-
_res = 0;
1535-
}
1536-
if (_res == 0) {
1537-
/* 2015-05-07, 1.10 */
1538-
Py_DECREF(array_other);
1539-
if (DEPRECATE_FUTUREWARNING(
1540-
"elementwise == comparison failed and returning scalar "
1541-
"instead; this will raise an error or perform "
1542-
"elementwise comparison in the future.") < 0) {
1543-
return NULL;
1544-
}
1545-
Py_INCREF(Py_False);
1546-
return Py_False;
1547-
}
1548-
else {
1549-
result = _void_compare(self, array_other, cmp_op);
1550-
}
1551-
Py_DECREF(array_other);
1552-
return result;
1523+
if (HPyArray_GetType(ctx, self) == NPY_VOID) {
1524+
hpy_abort_not_implemented("void arrays in rich compare");
1525+
// int _res;
1526+
1527+
// array_other = (PyArrayObject *)PyArray_FROM_O(other);
1528+
// /*
1529+
// * If not successful, indicate that the items cannot be compared
1530+
// * this way.
1531+
// */
1532+
// if (array_other == NULL) {
1533+
// /* 2015-05-07, 1.10 */
1534+
// if (DEPRECATE_silence_error(
1535+
// "elementwise == comparison failed and returning scalar "
1536+
// "instead; this will raise an error in the future.") < 0) {
1537+
// return NULL;
1538+
// }
1539+
// Py_INCREF(Py_NotImplemented);
1540+
// return Py_NotImplemented;
1541+
// }
1542+
1543+
// _res = PyArray_CheckCastSafety(
1544+
// NPY_EQUIV_CASTING,
1545+
// PyArray_DESCR(self), PyArray_DESCR(array_other), NULL);
1546+
// if (_res < 0) {
1547+
// PyErr_Clear();
1548+
// _res = 0;
1549+
// }
1550+
// if (_res == 0) {
1551+
// /* 2015-05-07, 1.10 */
1552+
// Py_DECREF(array_other);
1553+
// if (DEPRECATE_FUTUREWARNING(
1554+
// "elementwise == comparison failed and returning scalar "
1555+
// "instead; this will raise an error or perform "
1556+
// "elementwise comparison in the future.") < 0) {
1557+
// return NULL;
1558+
// }
1559+
// Py_INCREF(Py_False);
1560+
// return Py_False;
1561+
// }
1562+
// else {
1563+
// result = _void_compare(self, array_other, cmp_op);
1564+
// }
1565+
// Py_DECREF(array_other);
1566+
// return result;
15531567
}
15541568

1555-
result = PyArray_GenericBinaryFunction(
1556-
(PyObject *)self, (PyObject *)other, N_OPS_GET(equal));
1569+
result = HPyArray_GenericBinaryFunction(
1570+
ctx, self, other, hpy_n_ops.equal);
15571571
break;
15581572
case Py_NE:
1559-
RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
1573+
HPY_RICHCMP_GIVE_UP_IF_NEEDED(ctx, self, other);
15601574
/*
15611575
* The ufunc does not support void/structured types, so these
15621576
* need to be handled specifically. Only a few cases are supported.
15631577
*/
15641578

1565-
if (PyArray_TYPE(self) == NPY_VOID) {
1566-
int _res;
1567-
1568-
array_other = (PyArrayObject *)PyArray_FROM_O(other);
1569-
/*
1570-
* If not successful, indicate that the items cannot be compared
1571-
* this way.
1572-
*/
1573-
if (array_other == NULL) {
1574-
/* 2015-05-07, 1.10 */
1575-
if (DEPRECATE_silence_error(
1576-
"elementwise != comparison failed and returning scalar "
1577-
"instead; this will raise an error in the future.") < 0) {
1578-
return NULL;
1579-
}
1580-
Py_INCREF(Py_NotImplemented);
1581-
return Py_NotImplemented;
1582-
}
1583-
1584-
_res = PyArray_CheckCastSafety(
1585-
NPY_EQUIV_CASTING,
1586-
PyArray_DESCR(self), PyArray_DESCR(array_other), NULL);
1587-
if (_res < 0) {
1588-
PyErr_Clear();
1589-
_res = 0;
1590-
}
1591-
if (_res == 0) {
1592-
/* 2015-05-07, 1.10 */
1593-
Py_DECREF(array_other);
1594-
if (DEPRECATE_FUTUREWARNING(
1595-
"elementwise != comparison failed and returning scalar "
1596-
"instead; this will raise an error or perform "
1597-
"elementwise comparison in the future.") < 0) {
1598-
return NULL;
1599-
}
1600-
Py_INCREF(Py_True);
1601-
return Py_True;
1602-
}
1603-
else {
1604-
result = _void_compare(self, array_other, cmp_op);
1605-
Py_DECREF(array_other);
1606-
}
1607-
return result;
1579+
if (HPyArray_GetType(ctx, self) == NPY_VOID) {
1580+
hpy_abort_not_implemented("void arrays in rich compare");
1581+
// int _res;
1582+
1583+
// array_other = (PyArrayObject *)PyArray_FROM_O(other);
1584+
// /*
1585+
// * If not successful, indicate that the items cannot be compared
1586+
// * this way.
1587+
// */
1588+
// if (array_other == NULL) {
1589+
// /* 2015-05-07, 1.10 */
1590+
// if (DEPRECATE_silence_error(
1591+
// "elementwise != comparison failed and returning scalar "
1592+
// "instead; this will raise an error in the future.") < 0) {
1593+
// return NULL;
1594+
// }
1595+
// Py_INCREF(Py_NotImplemented);
1596+
// return Py_NotImplemented;
1597+
// }
1598+
1599+
// _res = PyArray_CheckCastSafety(
1600+
// NPY_EQUIV_CASTING,
1601+
// PyArray_DESCR(self), PyArray_DESCR(array_other), NULL);
1602+
// if (_res < 0) {
1603+
// PyErr_Clear();
1604+
// _res = 0;
1605+
// }
1606+
// if (_res == 0) {
1607+
// /* 2015-05-07, 1.10 */
1608+
// Py_DECREF(array_other);
1609+
// if (DEPRECATE_FUTUREWARNING(
1610+
// "elementwise != comparison failed and returning scalar "
1611+
// "instead; this will raise an error or perform "
1612+
// "elementwise comparison in the future.") < 0) {
1613+
// return NULL;
1614+
// }
1615+
// Py_INCREF(Py_True);
1616+
// return Py_True;
1617+
// }
1618+
// else {
1619+
// result = _void_compare(self, array_other, cmp_op);
1620+
// Py_DECREF(array_other);
1621+
// }
1622+
// return result;
16081623
}
16091624

1610-
result = PyArray_GenericBinaryFunction(
1611-
(PyObject *)self, (PyObject *)other, N_OPS_GET(not_equal));
1625+
result = HPyArray_GenericBinaryFunction(
1626+
ctx, self, other, hpy_n_ops.not_equal);
16121627
break;
16131628
case Py_GT:
1614-
RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
1615-
result = PyArray_GenericBinaryFunction(
1616-
(PyObject *)self, other, N_OPS_GET(greater));
1629+
HPY_RICHCMP_GIVE_UP_IF_NEEDED(ctx, self, other);
1630+
result = HPyArray_GenericBinaryFunction(
1631+
ctx, self, other, hpy_n_ops.greater);
16171632
break;
16181633
case Py_GE:
1619-
RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
1620-
result = PyArray_GenericBinaryFunction(
1621-
(PyObject *)self, other, N_OPS_GET(greater_equal));
1634+
HPY_RICHCMP_GIVE_UP_IF_NEEDED(ctx, self, other);
1635+
result = HPyArray_GenericBinaryFunction(
1636+
ctx, self, other, hpy_n_ops.greater_equal);
16221637
break;
16231638
default:
1624-
Py_INCREF(Py_NotImplemented);
1625-
return Py_NotImplemented;
1639+
return HPy_Dup(ctx, ctx->h_NotImplemented);
16261640
}
1627-
if (result == NULL) {
1641+
if (HPy_IsNull(result)) {
16281642
/*
16291643
* 2015-05-14, 1.10; updated 2018-06-18, 1.16.
16301644
*
@@ -1650,7 +1664,8 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
16501664
* However, for backwards compatibility, we cannot yet return arrays,
16511665
* so we raise warnings instead.
16521666
*/
1653-
result = _failed_comparison_workaround(self, other, cmp_op);
1667+
hpy_abort_not_implemented("richcmp: _failed_comparison_workaround");
1668+
// result = _failed_comparison_workaround(self, other, cmp_op);
16541669
}
16551670
return result;
16561671
}
@@ -1952,7 +1967,6 @@ static PyType_Slot PyArray_Type_slots[] = {
19521967
{Py_tp_repr, (reprfunc)array_repr},
19531968
{Py_tp_str, (reprfunc)array_str},
19541969

1955-
{Py_tp_richcompare, (richcmpfunc)array_richcompare},
19561970
{Py_tp_iter, (getiterfunc)array_iter},
19571971
{Py_tp_methods, array_methods},
19581972
{Py_tp_getset, array_getsetlist},
@@ -1969,6 +1983,7 @@ static HPyDef *array_defines[] = {
19691983
&array_subtract,
19701984
&array_true_divide,
19711985
&array_add,
1986+
&array_richcompare_def,
19721987
NULL,
19731988
};
19741989

numpy/core/src/multiarray/number.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ _PyArray_GetNumericOps(void);
208208
NPY_NO_EXPORT PyObject *
209209
PyArray_GenericBinaryFunction(PyObject *m1, PyObject *m2, PyObject *op);
210210

211+
NPY_NO_EXPORT HPy
212+
HPyArray_GenericBinaryFunction(HPyContext *ctx, HPy m1, HPy m2, HPyGlobal op);
213+
211214
NPY_NO_EXPORT PyObject *
212215
PyArray_GenericUnaryFunction(PyArrayObject *m1, PyObject *op);
213216

0 commit comments

Comments
 (0)
0