numpy  2.0.0
src/multiarray/iterators.c File Reference
#include <Python.h>
#include "structmember.h"
#include "numpy/arrayobject.h"
#include "numpy/arrayscalars.h"
#include "npy_config.h"
#include "npy_pycompat.h"
#include "arrayobject.h"
#include "iterators.h"
#include "ctors.h"
#include "common.h"

Defines

#define PY_SSIZE_T_CLEAN
#define NPY_NO_DEPRECATED_API   NPY_API_VERSION
#define _MULTIARRAYMODULE
#define NEWAXIS_INDEX   -1
#define ELLIPSIS_INDEX   -2
#define SINGLE_INDEX   -3
#define _INF_SET_PTR(c)
#define _NPY_IS_EVEN(x)   ((x) % 2 == 0)
#define _INF_SET_PTR_MIRROR(c)
#define _INF_SET_PTR_CIRCULAR(c)

Functions

static int slice_coerce_index (PyObject *o, npy_intp *v)
NPY_NO_EXPORT npy_intp parse_index_entry (PyObject *op, npy_intp *step_size, npy_intp *n_steps, npy_intp max, int axis, int check_index)
NPY_NO_EXPORT int parse_index (PyArrayObject *self, PyObject *op, npy_intp *out_dimensions, npy_intp *out_strides, npy_intp *out_offset)
NPY_NO_EXPORT int slice_GetIndices (PySliceObject *r, npy_intp length, npy_intp *start, npy_intp *stop, npy_intp *step, npy_intp *slicelength)
static char * get_ptr_simple (PyArrayIterObject *iter, npy_intp *coordinates)
static PyObject * array_iter_base_init (PyArrayIterObject *it, PyArrayObject *ao)
static void array_iter_base_dealloc (PyArrayIterObject *it)
NPY_NO_EXPORT PyObject * PyArray_IterNew (PyObject *obj)
NPY_NO_EXPORT PyObject * PyArray_BroadcastToShape (PyObject *obj, npy_intp *dims, int nd)
NPY_NO_EXPORT PyObject * PyArray_IterAllButAxis (PyObject *obj, int *inaxis)
NPY_NO_EXPORT int PyArray_RemoveSmallest (PyArrayMultiIterObject *multi)
static PyObject * arrayiter_next (PyArrayIterObject *it)
static void arrayiter_dealloc (PyArrayIterObject *it)
static Py_ssize_t iter_length (PyArrayIterObject *self)
static PyArrayObjectiter_subscript_Bool (PyArrayIterObject *self, PyArrayObject *ind)
static PyObject * iter_subscript_int (PyArrayIterObject *self, PyArrayObject *ind)
NPY_NO_EXPORT PyObject * iter_subscript (PyArrayIterObject *self, PyObject *ind)
static int iter_ass_sub_Bool (PyArrayIterObject *self, PyArrayObject *ind, PyArrayIterObject *val, int swap)
static int iter_ass_sub_int (PyArrayIterObject *self, PyArrayObject *ind, PyArrayIterObject *val, int swap)
NPY_NO_EXPORT int iter_ass_subscript (PyArrayIterObject *self, PyObject *ind, PyObject *val)
static PyArrayObjectiter_array (PyArrayIterObject *it, PyObject *NPY_UNUSED(op))
static PyObject * iter_copy (PyArrayIterObject *it, PyObject *args)
static PyObject * iter_richcompare (PyArrayIterObject *self, PyObject *other, int cmp_op)
static PyObject * iter_coords_get (PyArrayIterObject *self)
NPY_NO_EXPORT int PyArray_Broadcast (PyArrayMultiIterObject *mit)
NPY_NO_EXPORT PyObject * PyArray_MultiIterFromObjects (PyObject **mps, int n, int nadd,...)
NPY_NO_EXPORT PyObject * PyArray_MultiIterNew (int n,...)
static PyObject * arraymultiter_new (PyTypeObject *NPY_UNUSED(subtype), PyObject *args, PyObject *kwds)
static PyObject * arraymultiter_next (PyArrayMultiIterObject *multi)
static void arraymultiter_dealloc (PyArrayMultiIterObject *multi)
static PyObject * arraymultiter_size_get (PyArrayMultiIterObject *self)
static PyObject * arraymultiter_index_get (PyArrayMultiIterObject *self)
static PyObject * arraymultiter_shape_get (PyArrayMultiIterObject *self)
static PyObject * arraymultiter_iters_get (PyArrayMultiIterObject *self)
static PyObject * arraymultiter_reset (PyArrayMultiIterObject *self, PyObject *args)
static void neighiter_dealloc (PyArrayNeighborhoodIterObject *iter)
static char * _set_constant (PyArrayNeighborhoodIterObject *iter, PyArrayObject *fill)
static char * get_ptr_constant (PyArrayIterObject *_iter, npy_intp *coordinates)
static NPY_INLINE npy_intp __npy_pos_remainder (npy_intp i, npy_intp n)
static char * get_ptr_mirror (PyArrayIterObject *_iter, npy_intp *coordinates)
static NPY_INLINE npy_intp __npy_euclidean_division (npy_intp i, npy_intp n)
static char * get_ptr_circular (PyArrayIterObject *_iter, npy_intp *coordinates)
NPY_NO_EXPORT PyObject * PyArray_NeighborhoodIterNew (PyArrayIterObject *x, npy_intp *bounds, int mode, PyArrayObject *fill)

Variables

static PyMappingMethods iter_as_mapping
static PyMethodDef iter_methods []
static PyMemberDef iter_members []
static PyGetSetDef iter_getsets []
NPY_NO_EXPORT PyTypeObject PyArrayIter_Type
static PyGetSetDef arraymultiter_getsetlist []
static PyMemberDef arraymultiter_members []
static PyMethodDef arraymultiter_methods []
NPY_NO_EXPORT PyTypeObject PyArrayMultiIter_Type
NPY_NO_EXPORT PyTypeObject PyArrayNeighborhoodIter_Type

Define Documentation

#define _INF_SET_PTR (   c)
Value:
bd = coordinates[c] + p->coordinates[c]; \
    if (bd < p->limits[c][0] || bd > p->limits[c][1]) { \
        return niter->constant; \
    } \
    _coordinates[c] = bd;
#define _INF_SET_PTR_CIRCULAR (   c)
Value:
lb = p->limits[c][0]; \
    bd = coordinates[c] + p->coordinates[c] - lb; \
    _coordinates[c] = lb + __npy_euclidean_division(bd, p->limits_sizes[c]);
#define _INF_SET_PTR_MIRROR (   c)
Value:
lb = p->limits[c][0]; \
    bd = coordinates[c] + p->coordinates[c] - lb; \
    _coordinates[c] = lb + __npy_pos_remainder(bd, p->limits_sizes[c]);
#define _NPY_IS_EVEN (   x)    ((x) % 2 == 0)

Referenced by arraymultiter_new().

#define NPY_NO_DEPRECATED_API   NPY_API_VERSION

Function Documentation

compute l such as i = k * n + l, 0 <= l < |k|

Docutils System Messages

System Message: ERROR/3 (<string>, line 1); backlink Undefined substitution referenced: "k".
static NPY_INLINE npy_intp __npy_pos_remainder ( npy_intp  i,
npy_intp  n 
) [static]
For an array x of dimension n, and given index i, returns j, 0 <= j < n such as x[i] = x[j], with x assumed to be mirrored. For example, for x = {1, 2, 3} (n = 3)
index -5 -4 -3 -2 -1 0 1 2 3 4 5 6 value 2 3 3 2 1 1 2 3 3 2 1 1
_npy_pos_index_mirror(4, 3) will return 1, because x[4] = x[1]
Mirror i such as it is guaranteed to be positive
compute k and l such as i = k * n + l, 0 <= l < k
static char* _set_constant ( PyArrayNeighborhoodIterObject iter,
PyArrayObject fill 
) [static]
Non-object types
static void array_iter_base_dealloc ( PyArrayIterObject it) [static]

References PyArray_NDIM.

static PyObject* array_iter_base_init ( PyArrayIterObject it,
PyArrayObject ao 
) [static]
This is common initialization code between PyArrayIterObject and PyArrayNeighborhoodIterObject
Increase ao refcount

References PyArrayIterObject_tag::ao.

Referenced by arraymultiter_size_get().

static void arrayiter_dealloc ( PyArrayIterObject it) [static]
static PyObject* arrayiter_next ( PyArrayIterObject it) [static]
Returns an array scalar holding the element desired
static void arraymultiter_dealloc ( PyArrayMultiIterObject multi) [static]
static PyObject* arraymultiter_index_get ( PyArrayMultiIterObject self) [static]
static PyObject* arraymultiter_iters_get ( PyArrayMultiIterObject self) [static]
static PyObject* arraymultiter_new ( PyTypeObject *  NPY_UNUSEDsubtype,
PyObject *  args,
PyObject *  kwds 
) [static]

References _NPY_IS_EVEN.

Referenced by PyArray_MultiIterFromObjects().

static PyObject* arraymultiter_next ( PyArrayMultiIterObject multi) [static]
static PyObject* arraymultiter_reset ( PyArrayMultiIterObject self,
PyObject *  args 
) [static]
static PyObject* arraymultiter_shape_get ( PyArrayMultiIterObject self) [static]
static char* get_ptr_circular ( PyArrayIterObject _iter,
npy_intp coordinates 
) [static]
static char* get_ptr_constant ( PyArrayIterObject _iter,
npy_intp coordinates 
) [static]
set the dataptr from its current coordinates
static char* get_ptr_mirror ( PyArrayIterObject _iter,
npy_intp coordinates 
) [static]
set the dataptr from its current coordinates
static char* get_ptr_simple ( PyArrayIterObject iter,
npy_intp coordinates 
) [static]
***************** Element-wise Array Iterator ******************
Aided by Peter J. Verveer's nd_image package and numpy's arraymap ***

System Message: WARNING/2 (<string>, line 1); backlink Inline strong start-string without end-string.
System Message: WARNING/2 (<string>, line 1); backlink Inline emphasis start-string without end-string.
and Python's array iterator **
get the dataptr from its current coordinates for simple iterator

References PyArrayIterObject_tag::backstrides, PyArrayIterObject_tag::bounds, PyArrayIterObject_tag::dims_m1, PyArrayIterObject_tag::factors, PyArrayIterObject_tag::limits, PyArrayIterObject_tag::limits_sizes, PyArray_DIMS, PyArray_STRIDES, and PyArrayIterObject_tag::strides.

static PyArrayObject* iter_array ( PyArrayIterObject it,
PyObject *  NPY_UNUSEDop 
) [static]
Any argument ignored
Two options:
  1. underlying array is contiguous -- return 1-d wrapper around it

  2. underlying array is not contiguous -- make new 1-d contiguous array with updateifcopy flag set

    System Message: ERROR/3 (<string>, line 6)
    Unexpected indentation.

    <blockquote>

    to copy back to the old array </blockquote>

If underlying array is readonly, then we make the output array readonly
and updateifcopy does not apply.
static int iter_ass_sub_Bool ( PyArrayIterObject self,
PyArrayObject ind,
PyArrayIterObject val,
int  swap 
) [static]
Loop over Boolean array
static int iter_ass_sub_int ( PyArrayIterObject self,
PyArrayObject ind,
PyArrayIterObject val,
int  swap 
) [static]
NPY_NO_EXPORT int iter_ass_subscript ( PyArrayIterObject self,
PyObject *  ind,
PyObject *  val 
)
Check for Boolean -- this is first becasue Bool is a subclass of Int
Check Slice
Integer
convert to INTP array if Integer array scalar or List
Check for Boolean object
Check for integer array

References PyArrayIterObject_tag::dataptr, ELLIPSIS_INDEX, PyArrayIterObject_tag::index, NEWAXIS_INDEX, parse_index_entry(), PyArray_DATA, PyArray_ITER_GOTO1D, PyArray_ITER_NEXT, PyArray_ITER_RESET, SINGLE_INDEX, and PyArrayIterObject_tag::size.

static PyObject* iter_coords_get ( PyArrayIterObject self) [static]
coordinates not kept track of --- need to generate from index
static PyObject* iter_copy ( PyArrayIterObject it,
PyObject *  args 
) [static]
static Py_ssize_t iter_length ( PyArrayIterObject self) [static]
static PyObject* iter_richcompare ( PyArrayIterObject self,
PyObject *  other,
int  cmp_op 
) [static]
NPY_NO_EXPORT PyObject* iter_subscript ( PyArrayIterObject self,
PyObject *  ind 
)
Always returns arrays
Tuples >1d not accepted --- i.e. no newaxis Could implement this with adjusted strides and dimensions in iterator Check for Boolean -- this is first because Bool is a subclass of Int

<

empty array
Check for Integer or Slice

<

Integer
convert to INTP array if Integer array scalar or List
Check for Boolean object
Check for integer array

Referenced by iter_subscript_int().

static PyArrayObject* iter_subscript_Bool ( PyArrayIterObject self,
PyArrayObject ind 
) [static]
Get size of return array
Set up loop
Loop over Boolean array
static void neighiter_dealloc ( PyArrayNeighborhoodIterObject iter) [static]
========================= Neighborhood iterator ======================
NPY_NO_EXPORT int parse_index ( PyArrayObject self,
PyObject *  op,
npy_intp out_dimensions,
npy_intp out_strides,
npy_intp out_offset 
)
Parses an index that has no fancy indexing. Populates out_dimensions, out_strides, and out_offset.
this relies on the fact that n==1 for loop below

References ELLIPSIS_INDEX, NEWAXIS_INDEX, parse_index_entry(), PyArray_DIMS, PyArray_NDIM, PyArray_STRIDES, and SINGLE_INDEX.

Referenced by fancy_indexing_check().

NPY_NO_EXPORT npy_intp parse_index_entry ( PyObject *  op,
npy_intp step_size,
npy_intp n_steps,
npy_intp  max,
int  axis,
int  check_index 
)
This function converts one element of the indexing tuple into a step size and a number of steps, returning the starting index. Non-slices are signalled in 'n_steps', as NEWAXIS_INDEX, ELLIPSIS_INDEX, or SINGLE_INDEX.

References check_and_adjust_index(), ELLIPSIS_INDEX, NEWAXIS_INDEX, SINGLE_INDEX, slice_coerce_index(), and slice_GetIndices().

Referenced by iter_ass_subscript(), iter_subscript_int(), and parse_index().

END of Array Iterator *
Adjust dimensionality and strides for index object iterators
--- i.e. broadcast
Discover the broadcast number of dimensions
Discover the broadcast shape in each dimension
This prepends 1 to shapes not already equal to nd
Reset the iterator dimensions and strides of each iterator object -- using 0 valued strides for broadcasting Need to check for overflow
If this dimension was added or shape of underlying array was 1
NPY_NO_EXPORT PyObject* PyArray_IterAllButAxis ( PyObject *  obj,
int *  inaxis 
)
Get Iterator that iterates over all but one axis (don't use this with
PyArray_ITER_GOTO1D). The axis will be over-written if negative with the axis having the smallest stride.
adjust so that will not iterate over axis
(won't fix factors so don't use PyArray_ITER_GOTO1D with this iterator)
NPY_NO_EXPORT PyObject* PyArray_IterNew ( PyObject *  obj)
Get Iterator.
it = PyObject_New(PyArrayIterObject, &PyArrayIter_Type);

Referenced by _deepcopy_call(), _nonzero_indices(), and PyArray_ToFile().

NPY_NO_EXPORT PyObject* PyArray_MultiIterFromObjects ( PyObject **  mps,
int  n,
int  nadd,
  ... 
)
Get MultiIterator from array of Python objects and any additional <blockquote>
PyObject **mps -- array of PyObjects int n - number of PyObjects in the array int nadd - number of additional arrays to include in the iterator.

System Message: WARNING/2 (<string>, line 3); backlink Inline strong start-string without end-string.
Returns a multi-iterator object. </blockquote>

References arraymultiter_dealloc(), arraymultiter_new(), and arraymultiter_next().

NPY_NO_EXPORT PyObject* PyArray_MultiIterNew ( int  n,
  ... 
)
Get MultiIterator,
fprintf(stderr, "multi new...");
NPY_NO_EXPORT PyObject* PyArray_NeighborhoodIterNew ( PyArrayIterObject x,
npy_intp bounds,
int  mode,
PyArrayObject fill 
)
fill and x->ao should have equivalent types
A Neighborhood Iterator object.
Compute the neighborhood size and copy the shape
limits keep track of valid ranges for the neighborhood: if a bound of the neighborhood is outside the array, then limits is the same as boundaries. On the contrary, if a bound is strictly inside the array, then limits correspond to the array range. For example, for an array [1, 2, 3], if bounds are [-1, 3], limits will be [-1, 3], but if bounds are [1, 2], then limits will be [0, 2].
This is used by neighborhood iterators stacked on top of this one
New reference in returned value of _set_constant if array object
XXX: we force x iterator to be non contiguous because we need coordinates... Modifying the iterator here is not great
Adjusts previously broadcasted iterators so that the axis with

the smallest sum of iterator strides is not iterated over. Returns dimension which is smallest in the range [0,multi->nd). A -1 is returned if multi->nd == 0.

don't use with PyArray_ITER_GOTO1D because factors are not adjusted

Find longest dimension
static int slice_coerce_index ( PyObject *  o,
npy_intp v 
) [static]
Tries to convert 'o' into an npy_intp interpreted as an index. Returns 1 if it was successful, 0 otherwise. Does not set an exception.
PyNumber_Index was introduced in Python 2.5 because of NumPy. http://www.python.org/dev/peps/pep-0357/ Let's use it for indexing!
Unfortunately, SciPy and possibly other code seems to rely on the lenient coercion. :(

<

PY_VERSION_HEX >= 0x02050000

Referenced by parse_index_entry().

NPY_NO_EXPORT int slice_GetIndices ( PySliceObject *  r,
npy_intp  length,
npy_intp start,
npy_intp stop,
npy_intp step,
npy_intp slicelength 
)
This is basically PySlice_GetIndicesEx, but with our coercion of indices to integers (plus, that function is new in Python 2.3)
defstart = *step < 0 ? length - 1 : 0;

System Message: WARNING/2 (<string>, line 1); backlink Inline emphasis start-string without end-string.

Referenced by _nonzero_indices(), and parse_index_entry().


Variable Documentation

PyGetSetDef arraymultiter_getsetlist[] [static]
Initial value:
 {
    {"size",
        (getter)arraymultiter_size_get,
        NULL,
        NULL, NULL},
    {"index",
        (getter)arraymultiter_index_get,
        NULL,
        NULL, NULL},
    {"shape",
        (getter)arraymultiter_shape_get,
        NULL,
        NULL, NULL},
    {"iters",
        (getter)arraymultiter_iters_get,
        NULL,
        NULL, NULL},
    {NULL, NULL, NULL, NULL, NULL},
}
PyMemberDef arraymultiter_members[] [static]
Initial value:
 {
    {"numiter",
        T_INT,
        offsetof(PyArrayMultiIterObject, numiter),
        READONLY, NULL},
    {"nd",
        T_INT,
        offsetof(PyArrayMultiIterObject, nd),
        READONLY, NULL},
    {NULL, 0, 0, 0, NULL},
}
PyMethodDef arraymultiter_methods[] [static]
Initial value:
 {
    {"reset",
        (PyCFunction) arraymultiter_reset,
        METH_VARARGS, NULL},
    {NULL, NULL, 0, NULL},      
}
PyMappingMethods iter_as_mapping [static]
Initial value:
 {






    (inquiry)iter_length,                   

    (binaryfunc)iter_subscript,             
    (objobjargproc)iter_ass_subscript,      
}
PyGetSetDef iter_getsets[] [static]
Initial value:
 {
    {"coords",
        (getter)iter_coords_get,
        NULL,
        NULL, NULL},
    {NULL, NULL, NULL, NULL, NULL},
}
PyMemberDef iter_members[] [static]
Initial value:
 {
    {"base",
        T_OBJECT,
        offsetof(PyArrayIterObject, ao),
        READONLY, NULL},
    {"index",
        T_INT,
        offsetof(PyArrayIterObject, index),
        READONLY, NULL},
    {NULL, 0, 0, 0, NULL},
}
PyMethodDef iter_methods[] [static]
Initial value:
 {
    
    {"__array__",
        (PyCFunction)iter_array,
        METH_VARARGS, NULL},
    {"copy",
        (PyCFunction)iter_copy,
        METH_VARARGS, NULL},
    {NULL, NULL, 0, NULL}           
}