10BC0 API: Remove The MapIter API from public by seberg · Pull Request #25138 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions doc/release/upcoming_changes/25138.c_api_removal.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
* The advanced indexing ``MapIter`` and related API has been removed.
The (truly) public part of it was not well tested and had only one
known user (Theano). Making it private will simplify improvements
to speed up ``ufunc.at`` and make advanced indexing more maintainable
and was important for allowing 64 dimensional arrays.
Please let us know if this API is important to you so we can find a
solution together.
38 changes: 0 additions & 38 deletions doc/source/reference/c-api/array.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2674,44 +2674,6 @@ cost of a slight overhead.
neighborhood. Calling this function after every point of the
neighborhood has been visited is undefined.

Array mapping
-------------

Array mapping is the machinery behind advanced indexing.

.. c:function:: PyObject* PyArray_MapIterArray(PyArrayObject *a, \
PyObject *index)

Use advanced indexing to iterate an array.

.. c:function:: void PyArray_MapIterSwapAxes(PyArrayMapIterObject *mit, \
PyArrayObject **ret, int getmap)

Swap the axes to o 10BC0 r from their inserted form. ``MapIter`` always puts the
advanced (array) indices first in the iteration. But if they are
consecutive, it will insert/transpose them back before returning.
This is stored as ``mit->consec != 0`` (the place where they are inserted).
For assignments, the opposite happens: the values to be assigned are
transposed (``getmap=1`` instead of ``getmap=0``). ``getmap=0`` and
``getmap=1`` undo the other operation.

.. c:function:: void PyArray_MapIterNext(PyArrayMapIterObject *mit)

This function needs to update the state of the map iterator
and point ``mit->dataptr`` to the memory-location of the next object.

Note that this function never handles an extra operand but provides
compatibility for an old (exposed) API.

.. c:function:: PyObject* PyArray_MapIterArrayCopyIfOverlap(PyArrayObject *a, \
PyObject *index, int copy_if_overlap, PyArrayObject *extra_op)

Similar to :c:func:`PyArray_MapIterArray` but with an additional
``copy_if_overlap`` argument. If ``copy_if_overlap != 0``, checks if ``a``
has memory overlap with any of the arrays in ``index`` and with
``extra_op``, and make copies as appropriate to avoid problems if the
input is modified during the iteration. ``iter->array`` may contain a
copied array (WRITEBACKIFCOPY set).

Array scalars
-------------
Expand Down
2 changes: 1 addition & 1 deletion numpy/_core/code_generators/cversions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,4 @@
0x00000011 = ca1aebdad799358149567d9d93cbca09

# Version 18 (NumPy 2.0.0)
0x00000012 = c48425db43c108beeb57eb7ef155d38e
0x00000012 = 36c48c1b8952883ca3a636cedaeb441f
1 change: 0 additions & 1 deletion numpy/_core/code_generators/generate_numpy_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
npy_bool obval;
} PyBoolScalarObject;

extern NPY_NO_EXPORT PyTypeObject PyArrayMapIter_Type;
extern NPY_NO_EXPORT PyTypeObject PyArrayNeighborhoodIter_Type;
extern NPY_NO_EXPORT PyBoolScalarObject _PyArrayScalar_BoolValues[2];

Expand Down
11 changes: 6 additions & 5 deletions numpy/_core/code_generators/numpy_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ def get_annotations():

multiarray_funcs_api = {
'__unused_indices__': [
40, 41, 65, 67, 68, 163, 164, 171, 201, 202, 278, 291],
40, 41, 65, 67, 68, 163, 164, 171, 201, 202, 278, 291, 293, 294, 295,
301],
'PyArray_GetNDArrayCVersion': (0,),
# Unused slot 40, was `PyArray_SetNumericOps`
# Unused slot 41, was `PyArray_GetNumericOps`,
Expand Down Expand Up @@ -352,9 +353,9 @@ def get_annotations():
'PyDataMem_FREE': (289,),
'PyDataMem_RENEW': (290,),
# Unused slot 291, was `PyDataMem_SetEventHook`
'PyArray_MapIterSwapAxes': (293,),
'PyArray_MapIterArray': (294,),
'PyArray_MapIterNext': (295,),
# Unused slot 293, was `PyArray_MapIterSwapAxes`
# Unused slot 294, was `PyArray_MapIterArray`
# Unused slot 295, was `PyArray_MapIterNext`
# End 1.7 API
'PyArray_Partition': (296,),
'PyArray_ArgPartition': (297,),
Expand All @@ -364,7 +365,7 @@ def get_annotations():
# End 1.9 API
'PyArray_CheckAnyScalarExact': (300,),
# End 1.10 API
'PyArray_MapIterArrayCopyIfOverlap': (301,),
# Unused slot 301, was `PyArray_MapIterArrayCopyIfOverlap`
# End 1.13 API
'PyArray_ResolveWritebackIfCopy': (302,),
'PyArray_SetWritebackIfCopyBase': (303,),
Expand Down
89 changes: 0 additions & 89 deletions numpy/_core/include/numpy/ndarraytypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1319,95 +1319,6 @@ PyArray_MultiIter_ITERS(PyArrayMultiIterObject *multi)
}


/*
* Store the information needed for fancy-indexing over an array. The
* fields are slightly unordered to keep consec, dataptr and subspace
* where they were originally.
*/
typedef struct {
PyObject_HEAD
/*
* Multi-iterator portion --- needs to be present in this
* order to work with PyArray_Broadcast
*/

int numiter; /* number of index-array
iterators */
npy_intp size; /* size of broadcasted
result */
npy_intp index; /* current index */
int nd; /* number of dims */
npy_intp dimensions[NPY_MAXDIMS]; /* dimensions */
NpyIter *outer; /* index objects
iterator */
void *unused[NPY_MAXDIMS - 2];
PyArrayObject *array;
/* Flat iterator for the indexed array. For compatibility solely. */
PyArrayIterObject *ait;

/*
* Subspace array. For binary compatibility (was an iterator,
* but only the check for NULL should be used).
*/
PyArrayObject *subspace;

/*
* if subspace iteration, then this is the array of axes in
* the underlying array represented by the index objects
*/
int iteraxes[NPY_MAXDIMS];
npy_intp fancy_strides[NPY_MAXDIMS];

/* pointer when all fancy indices are 0 */
char *baseoffset;

/*
* after binding consec denotes at which axis the fancy axes
* are inserted.
*/
int consec;
char *dataptr;

int nd_fancy;
npy_intp fancy_dims[NPY_MAXDIMS];

/*
* Whether the iterator (any of the iterators) requires API. This is
* unused by NumPy itself; ArrayMethod flags are more precise.
*/
int needs_api;

/*
* Extra op information.
*/
PyArrayObject *extra_op;
PyArray_Descr *extra_op_dtype; /* desired dtype */
npy_uint32 *extra_op_flags; /* Iterator flags */

NpyIter *extra_op_iter;
NpyIter_IterNextFunc *extra_op_next;
char **extra_op_ptrs;

/*
* Information about the iteration state.
*/
NpyIter_IterNextFunc *outer_next;
char **outer_ptrs;
npy_intp *outer_strides;

/*
* Information about the subspace iterator.
*/
NpyIter *subspace_iter;
NpyIter_IterNextFunc *subspace_next;
char **subspace_ptrs;
npy_intp *subspace_strides;

/* Count for the external loop (which ever it is) for API iteration */
npy_intp iter_count;

} PyArrayMapIterObject;

enum {
NPY_NEIGHBORHOOD_ITER_ZERO_PADDING,
NPY_NEIGHBORHOOD_ITER_ONE_PADDING,
Expand Down
1 change: 1 addition & 0 deletions numpy/_core/src/common/lowlevel_strided_loops.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "array_method.h"
#include "dtype_transfer.h"
#include "mem_overlap.h"
#include "mapping.h"

/* For PyArray_ macros used below */
#include "numpy/ndarrayobject.h"
Expand Down
129 changes: 0 additions & 129 deletions numpy/_core/src/multiarray/_multiarray_tests.c.src
Original file line number Diff line number Diff line change
Expand Up @@ -467,132 +467,6 @@ clean_ax:
}


typedef void (*inplace_map_binop)(PyArrayMapIterObject *, PyArrayIterObject *);

static void npy_float64_inplace_add(PyArrayMapIterObject *mit, PyArrayIterObject *it)
{
int index = mit->size;
while (index--) {
((npy_float64*)mit->dataptr)[0] = ((npy_float64*)mit->dataptr)[0] + ((npy_float64*)it->dataptr)[0];

PyArray_MapIterNext(mit);
PyArray_ITER_NEXT(it);
}
}

inplace_map_binop addition_funcs[] = {
npy_float64_inplace_add,
NULL};

int type_numbers[] = {
NPY_FLOAT64,
-1000};



static int
map_increment(PyArrayMapIterObject *mit, PyObject *op, inplace_map_binop add_inplace)
{
PyArrayObject *arr = NULL;
PyArrayIterObject *it;
PyArray_Descr *descr;

if (mit->ait == NULL) {
return -1;
}
descr = PyArray_DESCR(mit->ait->ao);
Py_INCREF(descr);
arr = (PyArrayObject *)PyArray_FromAny(op, descr,
0, 0, NPY_ARRAY_FORCECAST, NULL);
if (arr == NULL) {
return -1;
}

if ((mit->subspace != NULL) && (mit->consec)) {
PyArray_MapIterSwapAxes(mit, (PyArrayObject **)&arr, 0);
if (arr == NULL) {
return -1;
}
}

if ((it = (PyArrayIterObject *)\
PyArray_BroadcastToShape((PyObject *)arr, mit->dimensions,
mit->nd)) == NULL) {
Py_DECREF(arr);

return -1;
}

(*add_inplace)(mit, it);

Py_DECREF(arr);
Py_DECREF(it);
return 0;
}


static PyObject *
inplace_increment(PyObject *dummy, PyObject *args)
{
PyObject *arg_a = NULL, *index=NULL, *inc=NULL;
PyArrayObject *a;
inplace_map_binop add_inplace = NULL;
int type_number = -1;
int i =0;
PyArrayMapIterObject * mit;

if (!PyArg_ParseTuple(args, "OOO", &arg_a, &index,
&inc)) {
return NULL;
}
if (!PyArray_Check(arg_a)) {
PyErr_SetString(PyExc_ValueError, "needs an ndarray as first argument");
return NULL;
}
a = (PyArrayObject *) arg_a;

if (PyArray_FailUnlessWriteable(a, "input/output array") < 0) {
return NULL;
}

if (PyArray_NDIM(a) == 0) {
PyErr_SetString(PyExc_IndexError, "0-d arrays can't be indexed.");
return NULL;
}
type_number = PyArray_TYPE(a);

while (type_numbers[i] >= 0 && addition_funcs[i] != NULL){
if (type_number == type_numbers[i]) {
add_inplace = addition_funcs[i];
break;
}
i++ ;
}

if (add_inplace == NULL) {
PyErr_SetString(PyExc_TypeError, "unsupported type for a");
return NULL;
}

mit = (PyArrayMapIterObject *) PyArray_MapIterArray(a, index);
if (mit == NULL) {
goto fail;
}

if (map_increment(mit, inc, add_inplace) != 0) {
goto fail;
}

Py_DECREF(mit);

Py_RETURN_NONE;

fail:
Py_XDECREF(mit);

return NULL;
}

/*
* Helper to test fromstring of 0 terminated strings, as the C-API supports
* the -1 length identifier.
Expand Down Expand Up @@ -2302,9 +2176,6 @@ static PyMethodDef Multiarray_TestsMethods[] = {
{"test_neighborhood_iterator_oob",
test_neighborhood_iterator_oob,
METH_VARARGS, NULL},
{"test_inplace_increment",
inplace_increment,
METH_VARARGS, NULL},
{"fromstring_null_term_c_api",
fromstring_null_term_c_api,
METH_O, NULL},
Expand Down
Loading
0