summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Eendebak <pieter.eendebak@gmail.com>2023-01-23 18:58:02 +0100
committerGitHub <noreply@github.com>2023-01-23 18:58:02 +0100
commit172a1942893b5ce55abccd836fdd9f00235a6767 (patch)
treefb445f677bc077ea59afe6ebfa3d50cbe8c1248f
parenta701e87ce0b72a84afa839714fc78ded7783326d (diff)
downloadnumpy-172a1942893b5ce55abccd836fdd9f00235a6767.tar.gz
ENH: Convert methods to vectorcall conversions (#23018)
Convert several methods to the vectorcall convention. The conversions give a performance improvement, see #20790 (comment) Some notes: * For vdot the METH_KEYWORDS was removed, as the C vdot method was positional only. * The add_docstring is converted with an additional check. It was parsed as if (!PyArg_ParseTuple(args, "OO!:add_docstring", &obj, &PyUnicode_Type, &str)), but there is no support for the ! in the npy_parse_arguments * CI was complaining about coverage of _get_ndarray_c_version. A test was added, but only to provide coverage * In function_base.py a redundant check in def place was removed Co-authored-by: Sebastian Berg <sebastian@sipsolutions.net>
-rw-r--r--numpy/core/multiarray.py6
-rw-r--r--numpy/core/multiarray.pyi1
-rw-r--r--numpy/core/src/multiarray/compiled_base.c60
-rw-r--r--numpy/core/src/multiarray/compiled_base.h10
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.c122
-rw-r--r--numpy/core/src/umath/ufunc_object.c14
-rw-r--r--numpy/core/src/umath/ufunc_object.h4
-rw-r--r--numpy/core/tests/test_multiarray.py25
-rw-r--r--numpy/lib/function_base.py8
9 files changed, 159 insertions, 91 deletions
diff --git a/numpy/core/multiarray.py b/numpy/core/multiarray.py
index efb504240..ec1294b85 100644
--- a/numpy/core/multiarray.py
+++ b/numpy/core/multiarray.py
@@ -14,7 +14,7 @@ from ._multiarray_umath import * # noqa: F403
# do not change them. issue gh-15518
# _get_ndarray_c_version is semi-public, on purpose not added to __all__
from ._multiarray_umath import (
- fastCopyAndTranspose, _flagdict, from_dlpack, _insert, _reconstruct,
+ fastCopyAndTranspose, _flagdict, from_dlpack, _place, _reconstruct,
_vec_string, _ARRAY_API, _monotonicity, _get_ndarray_c_version,
_get_madvise_hugepage, _set_madvise_hugepage,
_get_promotion_state, _set_promotion_state,
@@ -25,7 +25,7 @@ __all__ = [
'ITEM_HASOBJECT', 'ITEM_IS_POINTER', 'LIST_PICKLE', 'MAXDIMS',
'MAY_SHARE_BOUNDS', 'MAY_SHARE_EXACT', 'NEEDS_INIT', 'NEEDS_PYAPI',
'RAISE', 'USE_GETITEM', 'USE_SETITEM', 'WRAP',
- '_flagdict', 'from_dlpack', '_insert', '_reconstruct', '_vec_string',
+ '_flagdict', 'from_dlpack', '_place', '_reconstruct', '_vec_string',
'_monotonicity', 'add_docstring', 'arange', 'array', 'asarray',
'asanyarray', 'ascontiguousarray', 'asfortranarray', 'bincount',
'broadcast', 'busday_count', 'busday_offset', 'busdaycalendar', 'can_cast',
@@ -1128,7 +1128,7 @@ def copyto(dst, src, casting=None, where=None):
@array_function_from_c_func_and_dispatcher(_multiarray_umath.putmask)
-def putmask(a, mask, values):
+def putmask(a, /, mask, values):
"""
putmask(a, mask, values)
diff --git a/numpy/core/multiarray.pyi b/numpy/core/multiarray.pyi
index 0701085b7..dc05f8126 100644
--- a/numpy/core/multiarray.pyi
+++ b/numpy/core/multiarray.pyi
@@ -428,6 +428,7 @@ def copyto(
def putmask(
a: NDArray[Any],
+ /,
mask: _ArrayLikeBool_co,
values: ArrayLike,
) -> None: ...
diff --git a/numpy/core/src/multiarray/compiled_base.c b/numpy/core/src/multiarray/compiled_base.c
index 2ae36c13a..22f2547ad 100644
--- a/numpy/core/src/multiarray/compiled_base.c
+++ b/numpy/core/src/multiarray/compiled_base.c
@@ -8,6 +8,7 @@
#include "numpy/arrayobject.h"
#include "numpy/npy_3kcompat.h"
#include "numpy/npy_math.h"
+#include "npy_argparse.h"
#include "npy_config.h"
#include "templ_common.h" /* for npy_mul_sizes_with_overflow */
#include "lowlevel_strided_loops.h" /* for npy_bswap8 */
@@ -109,7 +110,8 @@ minmax(const npy_intp *data, npy_intp data_len, npy_intp *mn, npy_intp *mx)
* output array.
*/
NPY_NO_EXPORT PyObject *
-arr_bincount(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwds)
+arr_bincount(PyObject *NPY_UNUSED(self), PyObject *const *args,
+ Py_ssize_t len_args, PyObject *kwnames)
{
PyObject *list = NULL, *weight = Py_None, *mlength = NULL;
PyArrayObject *lst = NULL, *ans = NULL, *wts = NULL;
@@ -117,11 +119,14 @@ arr_bincount(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwds)
npy_intp minlength = 0;
npy_intp i;
double *weights , *dans;
- static char *kwlist[] = {"list", "weights", "minlength", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO:bincount",
- kwlist, &list, &weight, &mlength)) {
- goto fail;
+ NPY_PREPARE_ARGPARSER;
+ if (npy_parse_arguments("bincount", args, len_args, kwnames,
+ "list", NULL, &list,
+ "|weights", NULL, &weight,
+ "|minlength", NULL, &mlength,
+ NULL, NULL, NULL) < 0) {
+ return NULL;
}
lst = (PyArrayObject *)PyArray_ContiguousFromAny(list, NPY_INTP, 1, 1);
@@ -265,7 +270,7 @@ arr__monotonicity(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwds)
* indicated by the mask
*/
NPY_NO_EXPORT PyObject *
-arr_insert(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwdict)
+arr_place(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwdict)
{
char *src, *dest;
npy_bool *mask_data;
@@ -489,7 +494,8 @@ binary_search_with_guess(const npy_double key, const npy_double *arr,
#undef LIKELY_IN_CACHE_SIZE
NPY_NO_EXPORT PyObject *
-arr_interp(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwdict)
+arr_interp(PyObject *NPY_UNUSED(self), PyObject *const *args, Py_ssize_t len_args,
+ PyObject *kwnames)
{
PyObject *fp, *xp, *x;
@@ -500,12 +506,16 @@ arr_interp(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwdict)
const npy_double *dy, *dx, *dz;
npy_double *dres, *slopes = NULL;
- static char *kwlist[] = {"x", "xp", "fp", "left", "right", NULL};
-
NPY_BEGIN_THREADS_DEF;
- if (!PyArg_ParseTupleAndKeywords(args, kwdict, "OOO|OO:interp", kwlist,
- &x, &xp, &fp, &left, &right)) {
+ NPY_PREPARE_ARGPARSER;
+ if (npy_parse_arguments("interp", args, len_args, kwnames,
+ "x", NULL, &x,
+ "xp", NULL, &xp,
+ "fp", NULL, &fp,
+ "|left", NULL, &left,
+ "|right", NULL, &right,
+ NULL, NULL, NULL) < 0) {
return NULL;
}
@@ -654,7 +664,8 @@ fail:
/* As for arr_interp but for complex fp values */
NPY_NO_EXPORT PyObject *
-arr_interp_complex(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwdict)
+arr_interp_complex(PyObject *NPY_UNUSED(self), PyObject *const *args, Py_ssize_t len_args,
+ PyObject *kwnames)
{
PyObject *fp, *xp, *x;
@@ -667,12 +678,16 @@ arr_interp_complex(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwdict)
npy_cdouble lval, rval;
npy_cdouble *dres, *slopes = NULL;
- static char *kwlist[] = {"x", "xp", "fp", "left", "right", NULL};
-
NPY_BEGIN_THREADS_DEF;
- if (!PyArg_ParseTupleAndKeywords(args, kwdict, "OOO|OO:interp_complex",
- kwlist, &x, &xp, &fp, &left, &right)) {
+ NPY_PREPARE_ARGPARSER;
+ if (npy_parse_arguments("interp_complex", args, len_args, kwnames,
+ "x", NULL, &x,
+ "xp", NULL, &xp,
+ "fp", NULL, &fp,
+ "|left", NULL, &left,
+ "|right", NULL, &right,
+ NULL, NULL, NULL) < 0) {
return NULL;
}
@@ -1389,7 +1404,7 @@ fail:
/* Can only be called if doc is currently NULL */
NPY_NO_EXPORT PyObject *
-arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args)
+arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *const *args, Py_ssize_t len_args)
{
PyObject *obj;
PyObject *str;
@@ -1401,7 +1416,16 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args)
Py_RETURN_NONE;
}
- if (!PyArg_ParseTuple(args, "OO!:add_docstring", &obj, &PyUnicode_Type, &str)) {
+ NPY_PREPARE_ARGPARSER;
+ if (npy_parse_arguments("add_docstring", args, len_args, NULL,
+ "", NULL, &obj,
+ "", NULL, &str,
+ NULL, NULL, NULL) < 0) {
+ return NULL;
+ }
+ if (!PyUnicode_Check(str)) {
+ PyErr_SetString(PyExc_TypeError,
+ "argument docstring of add_docstring should be a str");
return NULL;
}
diff --git a/numpy/core/src/multiarray/compiled_base.h b/numpy/core/src/multiarray/compiled_base.h
index d3bc08cb2..e0e73ac79 100644
--- a/numpy/core/src/multiarray/compiled_base.h
+++ b/numpy/core/src/multiarray/compiled_base.h
@@ -4,21 +4,21 @@
#include "numpy/ndarraytypes.h"
NPY_NO_EXPORT PyObject *
-arr_insert(PyObject *, PyObject *, PyObject *);
+arr_place(PyObject *, PyObject *, PyObject *);
NPY_NO_EXPORT PyObject *
-arr_bincount(PyObject *, PyObject *, PyObject *);
+arr_bincount(PyObject *, PyObject *const *, Py_ssize_t, PyObject *);
NPY_NO_EXPORT PyObject *
arr__monotonicity(PyObject *, PyObject *, PyObject *kwds);
NPY_NO_EXPORT PyObject *
-arr_interp(PyObject *, PyObject *, PyObject *);
+arr_interp(PyObject *, PyObject *const *, Py_ssize_t, PyObject *, PyObject *);
NPY_NO_EXPORT PyObject *
-arr_interp_complex(PyObject *, PyObject *, PyObject *);
+arr_interp_complex(PyObject *, PyObject *const *, Py_ssize_t, PyObject *, PyObject *);
NPY_NO_EXPORT PyObject *
arr_ravel_multi_index(PyObject *, PyObject *, PyObject *);
NPY_NO_EXPORT PyObject *
arr_unravel_index(PyObject *, PyObject *, PyObject *);
NPY_NO_EXPORT PyObject *
-arr_add_docstring(PyObject *, PyObject *);
+arr_add_docstring(PyObject *, PyObject *const *, Py_ssize_t);
NPY_NO_EXPORT PyObject *
io_pack(PyObject *, PyObject *, PyObject *);
NPY_NO_EXPORT PyObject *
diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c
index db9931e64..db7fda32d 100644
--- a/numpy/core/src/multiarray/multiarraymodule.c
+++ b/numpy/core/src/multiarray/multiarraymodule.c
@@ -1492,19 +1492,26 @@ fail:
return NULL;
}
-
static PyObject *
-array_putmask(PyObject *NPY_UNUSED(module), PyObject *args, PyObject *kwds)
+array_putmask(PyObject *NPY_UNUSED(module), PyObject *const *args,
+ Py_ssize_t len_args, PyObject *kwnames )
{
PyObject *mask, *values;
PyObject *array;
- static char *kwlist[] = {"arr", "mask", "values", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!OO:putmask", kwlist,
- &PyArray_Type, &array, &mask, &values)) {
+ NPY_PREPARE_ARGPARSER;
+ if (npy_parse_arguments("putmask", args, len_args, kwnames,
+ "", NULL, &array,
+ "mask", NULL, &mask,
+ "values", NULL, &values,
+ NULL, NULL, NULL) < 0) {
return NULL;
}
+ if (!PyArray_Check(array)) {
+ PyErr_SetString(PyExc_TypeError,
+ "argument a of putmask must be a numpy array");
+ }
+
return PyArray_PutMask((PyArrayObject *)array, values, mask);
}
@@ -2251,12 +2258,15 @@ fail:
}
static PyObject *
-array_count_nonzero(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwds)
+array_count_nonzero(PyObject *NPY_UNUSED(self), PyObject *const *args, Py_ssize_t len_args)
{
PyArrayObject *array;
npy_intp count;
- if (!PyArg_ParseTuple(args, "O&:count_nonzero", PyArray_Converter, &array)) {
+ NPY_PREPARE_ARGPARSER;
+ if (npy_parse_arguments("count_nonzero", args, len_args, NULL,
+ "", PyArray_Converter, &array,
+ NULL, NULL, NULL) < 0) {
return NULL;
}
@@ -2512,13 +2522,18 @@ array_concatenate(PyObject *NPY_UNUSED(dummy),
}
static PyObject *
-array_innerproduct(PyObject *NPY_UNUSED(dummy), PyObject *args)
+array_innerproduct(PyObject *NPY_UNUSED(dummy), PyObject *const *args, Py_ssize_t len_args)
{
PyObject *b0, *a0;
- if (!PyArg_ParseTuple(args, "OO:innerproduct", &a0, &b0)) {
- return NULL;
+ NPY_PREPARE_ARGPARSER;
+ if (npy_parse_arguments("innerproduct", args, len_args, NULL,
+ "", NULL, &a0,
+ "", NULL, &b0,
+ NULL, NULL, NULL) < 0) {
+ return NULL;
}
+
return PyArray_Return((PyArrayObject *)PyArray_InnerProduct(a0, b0));
}
@@ -2552,7 +2567,7 @@ array_matrixproduct(PyObject *NPY_UNUSED(dummy),
static PyObject *
-array_vdot(PyObject *NPY_UNUSED(dummy), PyObject *args)
+array_vdot(PyObject *NPY_UNUSED(dummy), PyObject *const *args, Py_ssize_t len_args)
{
int typenum;
char *ip1, *ip2, *op;
@@ -2565,7 +2580,11 @@ array_vdot(PyObject *NPY_UNUSED(dummy), PyObject *args)
PyArray_DotFunc *vdot;
NPY_BEGIN_THREADS_DEF;
- if (!PyArg_ParseTuple(args, "OO:vdot", &op1, &op2)) {
+ NPY_PREPARE_ARGPARSER;
+ if (npy_parse_arguments("vdot", args, len_args, NULL,
+ "", NULL, &op1,
+ "", NULL, &op2,
+ NULL, NULL, NULL) < 0) {
return NULL;
}
@@ -3142,13 +3161,9 @@ PyArray_GetNDArrayCFeatureVersion(void)
}
static PyObject *
-array__get_ndarray_c_version(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
+array__get_ndarray_c_version(
+ PyObject *NPY_UNUSED(dummy), PyObject *NPY_UNUSED(arg))
{
- static char *kwlist[] = {NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist )) {
- return NULL;
- }
return PyLong_FromLong( (long) PyArray_GetNDArrayCVersion() );
}
@@ -3443,24 +3458,34 @@ fail:
#undef INNER_WHERE_LOOP
static PyObject *
-array_where(PyObject *NPY_UNUSED(ignored), PyObject *args)
+array_where(PyObject *NPY_UNUSED(ignored), PyObject *const *args, Py_ssize_t len_args)
{
PyObject *obj = NULL, *x = NULL, *y = NULL;
- if (!PyArg_ParseTuple(args, "O|OO:where", &obj, &x, &y)) {
+ NPY_PREPARE_ARGPARSER;
+ if (npy_parse_arguments("where", args, len_args, NULL,
+ "", NULL, &obj,
+ "|x", NULL, &x,
+ "|y", NULL, &y,
+ NULL, NULL, NULL) < 0) {
return NULL;
}
+
return PyArray_Where(obj, x, y);
}
static PyObject *
-array_lexsort(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
+array_lexsort(PyObject *NPY_UNUSED(ignored), PyObject *const *args, Py_ssize_t len_args,
+ PyObject *kwnames)
{
int axis = -1;
PyObject *obj;
- static char *kwlist[] = {"keys", "axis", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:lexsort", kwlist, &obj, &axis)) {
+ NPY_PREPARE_ARGPARSER;
+ if (npy_parse_arguments("lexsort", args, len_args, kwnames,
+ "keys", NULL, &obj,
+ "|axis", PyArray_PythonPyIntFromInt, &axis,
+ NULL, NULL, NULL) < 0) {
return NULL;
}
return PyArray_Return((PyArrayObject *)PyArray_LexSort(obj, axis));
@@ -3525,13 +3550,17 @@ array_can_cast_safely(PyObject *NPY_UNUSED(self),
}
static PyObject *
-array_promote_types(PyObject *NPY_UNUSED(dummy), PyObject *args)
+array_promote_types(PyObject *NPY_UNUSED(dummy), PyObject *const *args, Py_ssize_t len_args)
{
PyArray_Descr *d1 = NULL;
PyArray_Descr *d2 = NULL;
PyObject *ret = NULL;
- if (!PyArg_ParseTuple(args, "O&O&:promote_types",
- PyArray_DescrConverter2, &d1, PyArray_DescrConverter2, &d2)) {
+
+ NPY_PREPARE_ARGPARSER;
+ if (npy_parse_arguments("promote_types", args, len_args, NULL,
+ "", PyArray_DescrConverter2, &d1,
+ "", PyArray_DescrConverter2, &d2,
+ NULL, NULL, NULL) < 0) {
goto finish;
}
@@ -3571,14 +3600,13 @@ array_min_scalar_type(PyObject *NPY_UNUSED(dummy), PyObject *args)
}
static PyObject *
-array_result_type(PyObject *NPY_UNUSED(dummy), PyObject *args)
+array_result_type(PyObject *NPY_UNUSED(dummy), PyObject *const *args, Py_ssize_t len)
{
- npy_intp i, len, narr = 0, ndtypes = 0;
+ npy_intp i, narr = 0, ndtypes = 0;
PyArrayObject **arr = NULL;
PyArray_Descr **dtypes = NULL;
PyObject *ret = NULL;
- len = PyTuple_GET_SIZE(args);
if (len == 0) {
PyErr_SetString(PyExc_ValueError,
"at least one array or dtype is required");
@@ -3592,7 +3620,7 @@ array_result_type(PyObject *NPY_UNUSED(dummy), PyObject *args)
dtypes = (PyArray_Descr**)&arr[len];
for (i = 0; i < len; ++i) {
- PyObject *obj = PyTuple_GET_ITEM(args, i);
+ PyObject *obj = args[i];
if (PyArray_Check(obj)) {
Py_INCREF(obj);
arr[narr] = (PyArrayObject *)obj;
@@ -4394,7 +4422,7 @@ static struct PyMethodDef array_module_methods[] = {
METH_VARARGS, NULL},
{"_get_ndarray_c_version",
(PyCFunction)array__get_ndarray_c_version,
- METH_VARARGS|METH_KEYWORDS, NULL},
+ METH_NOARGS, NULL},
{"_reconstruct",
(PyCFunction)array__reconstruct,
METH_VARARGS, NULL},
@@ -4439,7 +4467,7 @@ static struct PyMethodDef array_module_methods[] = {
METH_FASTCALL | METH_KEYWORDS, NULL},
{"count_nonzero",
(PyCFunction)array_count_nonzero,
- METH_VARARGS|METH_KEYWORDS, NULL},
+ METH_FASTCALL, NULL},
{"empty",
(PyCFunction)array_empty,
METH_FASTCALL | METH_KEYWORDS, NULL},
@@ -4451,13 +4479,13 @@ static struct PyMethodDef array_module_methods[] = {
METH_VARARGS|METH_KEYWORDS, NULL},
{"where",
(PyCFunction)array_where,
- METH_VARARGS, NULL},
+ METH_FASTCALL, NULL},
{"lexsort",
(PyCFunction)array_lexsort,
- METH_VARARGS | METH_KEYWORDS, NULL},
+ METH_FASTCALL | METH_KEYWORDS, NULL},
{"putmask",
(PyCFunction)array_putmask,
- METH_VARARGS | METH_KEYWORDS, NULL},
+ METH_FASTCALL | METH_KEYWORDS, NULL},
{"fromstring",
(PyCFunction)array_fromstring,
METH_VARARGS|METH_KEYWORDS, NULL},
@@ -4469,13 +4497,13 @@ static struct PyMethodDef array_module_methods[] = {
METH_FASTCALL|METH_KEYWORDS, NULL},
{"inner",
(PyCFunction)array_innerproduct,
- METH_VARARGS, NULL},
+ METH_FASTCALL, NULL},
{"dot",
(PyCFunction)array_matrixproduct,
METH_FASTCALL | METH_KEYWORDS, NULL},
{"vdot",
(PyCFunction)array_vdot,
- METH_VARARGS | METH_KEYWORDS, NULL},
+ METH_FASTCALL, NULL},
{"c_einsum",
(PyCFunction)array_einsum,
METH_VARARGS|METH_KEYWORDS, NULL},
@@ -4499,13 +4527,13 @@ static struct PyMethodDef array_module_methods[] = {
METH_FASTCALL | METH_KEYWORDS, NULL},
{"promote_types",
(PyCFunction)array_promote_types,
- METH_VARARGS, NULL},
+ METH_FASTCALL, NULL},
{"min_scalar_type",
(PyCFunction)array_min_scalar_type,
METH_VARARGS, NULL},
{"result_type",
(PyCFunction)array_result_type,
- METH_VARARGS, NULL},
+ METH_FASTCALL, NULL},
{"shares_memory",
(PyCFunction)array_shares_memory,
METH_VARARGS | METH_KEYWORDS, NULL},
@@ -4544,24 +4572,24 @@ static struct PyMethodDef array_module_methods[] = {
{"_vec_string",
(PyCFunction)_vec_string,
METH_VARARGS | METH_KEYWORDS, NULL},
- {"_insert", (PyCFunction)arr_insert,
+ {"_place", (PyCFunction)arr_place,
METH_VARARGS | METH_KEYWORDS,
"Insert vals sequentially into equivalent 1-d positions "
"indicated by mask."},
{"bincount", (PyCFunction)arr_bincount,
- METH_VARARGS | METH_KEYWORDS, NULL},
+ METH_FASTCALL | METH_KEYWORDS, NULL},
{"_monotonicity", (PyCFunction)arr__monotonicity,
METH_VARARGS | METH_KEYWORDS, NULL},
{"interp", (PyCFunction)arr_interp,
- METH_VARARGS | METH_KEYWORDS, NULL},
+ METH_FASTCALL | METH_KEYWORDS, NULL},
{"interp_complex", (PyCFunction)arr_interp_complex,
- METH_VARARGS | METH_KEYWORDS, NULL},
+ METH_FASTCALL | METH_KEYWORDS, NULL},
{"ravel_multi_index", (PyCFunction)arr_ravel_multi_index,
METH_VARARGS | METH_KEYWORDS, NULL},
{"unravel_index", (PyCFunction)arr_unravel_index,
METH_VARARGS | METH_KEYWORDS, NULL},
{"add_docstring", (PyCFunction)arr_add_docstring,
- METH_VARARGS, NULL},
+ METH_FASTCALL, NULL},
{"packbits", (PyCFunction)io_pack,
METH_VARARGS | METH_KEYWORDS, NULL},
{"unpackbits", (PyCFunction)io_unpack,
@@ -4584,10 +4612,10 @@ static struct PyMethodDef array_module_methods[] = {
METH_VARARGS | METH_KEYWORDS, NULL},
{"seterrobj",
(PyCFunction) ufunc_seterr,
- METH_VARARGS, NULL},
+ METH_O, NULL},
{"geterrobj",
(PyCFunction) ufunc_geterr,
- METH_VARARGS, NULL},
+ METH_NOARGS, NULL},
{"get_handler_name",
(PyCFunction) get_handler_name,
METH_VARARGS, NULL},
diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c
index eac09389e..792a373a5 100644
--- a/numpy/core/src/umath/ufunc_object.c
+++ b/numpy/core/src/umath/ufunc_object.c
@@ -5035,14 +5035,11 @@ ufunc_generic_vectorcall(PyObject *ufunc,
NPY_NO_EXPORT PyObject *
-ufunc_geterr(PyObject *NPY_UNUSED(dummy), PyObject *args)
+ufunc_geterr(PyObject *NPY_UNUSED(dummy), PyObject *NPY_UNUSED(arg))
{
PyObject *thedict;
PyObject *res;
-
- if (!PyArg_ParseTuple(args, "")) {
- return NULL;
- }
+
thedict = PyThreadState_GetDict();
if (thedict == NULL) {
thedict = PyEval_GetBuiltins();
@@ -5068,16 +5065,13 @@ ufunc_geterr(PyObject *NPY_UNUSED(dummy), PyObject *args)
NPY_NO_EXPORT PyObject *
-ufunc_seterr(PyObject *NPY_UNUSED(dummy), PyObject *args)
+ufunc_seterr(PyObject *NPY_UNUSED(dummy), PyObject *arg)
{
PyObject *thedict;
int res;
- PyObject *val;
+ PyObject *val = arg;
static char *msg = "Error object must be a list of length 3";
- if (!PyArg_ParseTuple(args, "O:seterrobj", &val)) {
- return NULL;
- }
if (!PyList_CheckExact(val) || PyList_GET_SIZE(val) != 3) {
PyErr_SetString(PyExc_ValueError, msg);
return NULL;
diff --git a/numpy/core/src/umath/ufunc_object.h b/numpy/core/src/umath/ufunc_object.h
index 45444dac4..1b80bb2df 100644
--- a/numpy/core/src/umath/ufunc_object.h
+++ b/numpy/core/src/umath/ufunc_object.h
@@ -4,10 +4,10 @@
#include <numpy/ufuncobject.h>
NPY_NO_EXPORT PyObject *
-ufunc_geterr(PyObject *NPY_UNUSED(dummy), PyObject *args);
+ufunc_geterr(PyObject *NPY_UNUSED(dummy), PyObject *NPY_UNUSED(arg));
NPY_NO_EXPORT PyObject *
-ufunc_seterr(PyObject *NPY_UNUSED(dummy), PyObject *args);
+ufunc_seterr(PyObject *NPY_UNUSED(dummy), PyObject *arg);
NPY_NO_EXPORT const char*
ufunc_get_name_cstr(PyUFuncObject *ufunc);
diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py
index fa39c1420..2d6f9c38c 100644
--- a/numpy/core/tests/test_multiarray.py
+++ b/numpy/core/tests/test_multiarray.py
@@ -33,6 +33,7 @@ from numpy.testing import (
from numpy.testing._private.utils import requires_memory, _no_tracing
from numpy.core.tests._locales import CommaDecimalPointLocale
from numpy.lib.recfunctions import repack_fields
+from numpy.core.multiarray import _get_ndarray_c_version
# Need to test an object that does not fully implement math interface
from datetime import timedelta, datetime
@@ -5084,6 +5085,22 @@ class TestPutmask:
with pytest.raises(ValueError):
np.putmask(a, a >= 2, 3)
+ def test_kwargs(self):
+ x = np.array([0, 0])
+ np.putmask(x, [0, 1], [-1, -2])
+ assert_array_equal(x, [0, -2])
+
+ x = np.array([0, 0])
+ np.putmask(x, mask=[0, 1], values=[-1, -2])
+ assert_array_equal(x, [0, -2])
+
+ x = np.array([0, 0])
+ np.putmask(x, values=[-1, -2], mask=[0, 1])
+ assert_array_equal(x, [0, -2])
+
+ with pytest.raises(TypeError):
+ np.putmask(a=x, values=[-1, -2], mask=[0, 1])
+
class TestTake:
def tst_basic(self, x):
@@ -8870,6 +8887,11 @@ class TestWhere:
result = array.nonzero()
assert_array_equal(benchmark, result)
+ def test_kwargs(self):
+ a = np.zeros(1)
+ with assert_raises(TypeError):
+ np.where(a, x=a, y=a)
+
if not IS_PYPY:
# sys.getsizeof() is not valid on PyPy
@@ -9882,3 +9904,6 @@ def test_sort_uint():
arr = rng.integers(low=0, high=maxv, size=N).astype('uint32')
arr[np.random.choice(arr.shape[0], 10)] = maxv
assert_equal(np.sort(arr, kind='quick'), np.sort(arr, kind='heap'))
+
+def test_private_get_ndarray_c_version():
+ assert isinstance(_get_ndarray_c_version(), int)
diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py
index d494aed0f..0ca3c21c1 100644
--- a/numpy/lib/function_base.py
+++ b/numpy/lib/function_base.py
@@ -24,7 +24,7 @@ from numpy.core import overrides
from numpy.core.function_base import add_newdoc
from numpy.lib.twodim_base import diag
from numpy.core.multiarray import (
- _insert, add_docstring, bincount, normalize_axis_index, _monotonicity,
+ _place, add_docstring, bincount, normalize_axis_index, _monotonicity,
interp as compiled_interp, interp_complex as compiled_interp_complex
)
from numpy.core.umath import _add_newdoc_ufunc as add_newdoc_ufunc
@@ -1949,11 +1949,7 @@ def place(arr, mask, vals):
[44, 55, 44]])
"""
- if not isinstance(arr, np.ndarray):
- raise TypeError("argument 1 must be numpy.ndarray, "
- "not {name}".format(name=type(arr).__name__))
-
- return _insert(arr, mask, vals)
+ return _place(arr, mask, vals)
def disp(mesg, device=None, linefeed=True):