numpy 2.0.0
src/multiarray/nditer_impl.h File Reference
#include "Python.h"
#include "structmember.h"
#include <numpy/ndarrayobject.h>
#include <numpy/npy_3kcompat.h>
#include "convert_datatype.h"
#include "lowlevel_strided_loops.h"

Go to the source code of this file.

Data Structures

struct  NpyIter_InternalOnly
struct  NpyIter_BD
struct  NpyIter_AD

Defines

#define PY_SSIZE_T_CLEAN
#define NPY_NO_DEPRECATED_API
#define _MULTIARRAYMODULE
#define NPY_IT_CONSTRUCTION_TIMING   0
#define NPY_IT_TIME_POINT(var)
#define NPY_IT_DBG_TRACING   0
#define NPY_IT_DBG_PRINT(s)
#define NPY_IT_DBG_PRINT1(s, p1)
#define NPY_IT_DBG_PRINT2(s, p1, p2)
#define NPY_IT_DBG_PRINT3(s, p1, p2, p3)
#define NPY_INTP_ALIGNED(size)   ((size + 0x7)&(-0x8))
#define NPY_ITFLAG_IDENTPERM   0x0001
#define NPY_ITFLAG_NEGPERM   0x0002
#define NPY_ITFLAG_HASINDEX   0x0004
#define NPY_ITFLAG_HASMULTIINDEX   0x0008
#define NPY_ITFLAG_FORCEDORDER   0x0010
#define NPY_ITFLAG_EXLOOP   0x0020
#define NPY_ITFLAG_RANGE   0x0040
#define NPY_ITFLAG_BUFFER   0x0080
#define NPY_ITFLAG_GROWINNER   0x0100
#define NPY_ITFLAG_ONEITERATION   0x0200
#define NPY_ITFLAG_DELAYBUF   0x0400
#define NPY_ITFLAG_NEEDSAPI   0x0800
#define NPY_ITFLAG_REDUCE   0x1000
#define NPY_ITFLAG_REUSE_REDUCE_LOOPS   0x2000
#define NPY_OP_ITFLAG_WRITE   0x01
#define NPY_OP_ITFLAG_READ   0x02
#define NPY_OP_ITFLAG_CAST   0x04
#define NPY_OP_ITFLAG_BUFNEVER   0x08
#define NPY_OP_ITFLAG_ALIGNED   0x10
#define NPY_OP_ITFLAG_REDUCE   0x20
#define NPY_OP_ITFLAG_VIRTUAL   0x40
#define NPY_OP_ITFLAG_WRITEMASKED   0x80
#define NIT_PERM_SIZEOF(itflags, ndim, nop)   NPY_INTP_ALIGNED(NPY_MAXDIMS)
#define NIT_DTYPES_SIZEOF(itflags, ndim, nop)   ((NPY_SIZEOF_INTP)*(nop))
#define NIT_RESETDATAPTR_SIZEOF(itflags, ndim, nop)   ((NPY_SIZEOF_INTP)*(nop+1))
#define NIT_BASEOFFSETS_SIZEOF(itflags, ndim, nop)   ((NPY_SIZEOF_INTP)*(nop+1))
#define NIT_OPERANDS_SIZEOF(itflags, ndim, nop)   ((NPY_SIZEOF_INTP)*(nop))
#define NIT_OPITFLAGS_SIZEOF(itflags, ndim, nop)   (NPY_INTP_ALIGNED(nop))
#define NIT_BUFFERDATA_SIZEOF(itflags, ndim, nop)   ((itflags&NPY_ITFLAG_BUFFER) ? ((NPY_SIZEOF_INTP)*(6 + 9*nop)) : 0)
#define NIT_PERM_OFFSET()   (0)
#define NIT_DTYPES_OFFSET(itflags, ndim, nop)
#define NIT_RESETDATAPTR_OFFSET(itflags, ndim, nop)
#define NIT_BASEOFFSETS_OFFSET(itflags, ndim, nop)
#define NIT_OPERANDS_OFFSET(itflags, ndim, nop)
#define NIT_OPITFLAGS_OFFSET(itflags, ndim, nop)
#define NIT_BUFFERDATA_OFFSET(itflags, ndim, nop)
#define NIT_AXISDATA_OFFSET(itflags, ndim, nop)
#define NIT_ITFLAGS(iter)   ((iter)->itflags)
#define NIT_NDIM(iter)   ((iter)->ndim)
#define NIT_NOP(iter)   ((iter)->nop)
#define NIT_MASKOP(iter)   ((iter)->maskop)
#define NIT_ITERSIZE(iter)   (iter->itersize)
#define NIT_ITERSTART(iter)   (iter->iterstart)
#define NIT_ITEREND(iter)   (iter->iterend)
#define NIT_ITERINDEX(iter)   (iter->iterindex)
#define NIT_PERM(iter)
#define NIT_DTYPES(iter)
#define NIT_RESETDATAPTR(iter)
#define NIT_BASEOFFSETS(iter)
#define NIT_OPERANDS(iter)
#define NIT_OPITFLAGS(iter)
#define NIT_BUFFERDATA(iter)
#define NIT_AXISDATA(iter)
#define NBF_BUFFERSIZE(bufferdata)   ((bufferdata)->buffersize)
#define NBF_SIZE(bufferdata)   ((bufferdata)->size)
#define NBF_BUFITEREND(bufferdata)   ((bufferdata)->bufiterend)
#define NBF_REDUCE_POS(bufferdata)   ((bufferdata)->reduce_pos)
#define NBF_REDUCE_OUTERSIZE(bufferdata)   ((bufferdata)->reduce_outersize)
#define NBF_REDUCE_OUTERDIM(bufferdata)   ((bufferdata)->reduce_outerdim)
#define NBF_STRIDES(bufferdata)
#define NBF_PTRS(bufferdata)
#define NBF_REDUCE_OUTERSTRIDES(bufferdata)
#define NBF_REDUCE_OUTERPTRS(bufferdata)
#define NBF_READTRANSFERFN(bufferdata)
#define NBF_READTRANSFERDATA(bufferdata)
#define NBF_WRITETRANSFERFN(bufferdata)
#define NBF_WRITETRANSFERDATA(bufferdata)
#define NBF_BUFFERS(bufferdata)
#define NAD_SHAPE(axisdata)   ((axisdata)->shape)
#define NAD_INDEX(axisdata)   ((axisdata)->index)
#define NAD_STRIDES(axisdata)
#define NAD_PTRS(axisdata)
#define NAD_NSTRIDES()   ((nop) + ((itflags&NPY_ITFLAG_HASINDEX) ? 1 : 0))
#define NIT_AXISDATA_SIZEOF(itflags, ndim, nop)
#define NIT_INDEX_AXISDATA(axisdata, index)
#define NIT_ADVANCE_AXISDATA(axisdata, count)   axisdata = NIT_INDEX_AXISDATA(axisdata, count)
#define NIT_SIZEOF_ITERATOR(itflags, ndim, nop)

Typedefs

typedef struct NpyIter_AD NpyIter_AxisData
typedef struct NpyIter_BD NpyIter_BufferData

Functions

NPY_NO_EXPORT void npyiter_coalesce_axes (NpyIter *iter)
NPY_NO_EXPORT int npyiter_allocate_buffers (NpyIter *iter, char **errmsg)
NPY_NO_EXPORT void npyiter_goto_iterindex (NpyIter *iter, npy_intp iterindex)
NPY_NO_EXPORT void npyiter_copy_from_buffers (NpyIter *iter)
NPY_NO_EXPORT void npyiter_copy_to_buffers (NpyIter *iter, char **prev_dataptrs)

Define Documentation

#define _MULTIARRAYMODULE
#define NAD_INDEX (   axisdata)    ((axisdata)->index)
#define NAD_NSTRIDES ( )    ((nop) + ((itflags&NPY_ITFLAG_HASINDEX) ? 1 : 0))
#define NAD_PTRS (   axisdata)
Value:
((char **) \
        &(axisdata)->ad_flexdata + 1*(nop+1))
#define NAD_STRIDES (   axisdata)
Value:
( \
        &(axisdata)->ad_flexdata + 0)

Referenced by npyiter_coalesce_axes().

#define NBF_BUFFERS (   bufferdata)
Value:
((char **) \
        (&(bufferdata)->bd_flexdata + 8*(nop)))

Referenced by NpyIter_Copy().

#define NBF_BUFFERSIZE (   bufferdata)    ((bufferdata)->buffersize)
#define NBF_BUFITEREND (   bufferdata)    ((bufferdata)->bufiterend)
#define NBF_PTRS (   bufferdata)
Value:
((char **) \
        (&(bufferdata)->bd_flexdata + 1*(nop)))

Referenced by NpyIter_GetBufferSize(), and NpyIter_GotoIndex().

#define NBF_READTRANSFERDATA (   bufferdata)
Value:
((NpyAuxData **) \
        (&(bufferdata)->bd_flexdata + 5*(nop)))

Referenced by NpyIter_Copy().

#define NBF_READTRANSFERFN (   bufferdata)
Value:
((PyArray_StridedTransferFn **) \
        (&(bufferdata)->bd_flexdata + 4*(nop)))
#define NBF_REDUCE_OUTERDIM (   bufferdata)    ((bufferdata)->reduce_outerdim)
#define NBF_REDUCE_OUTERPTRS (   bufferdata)
Value:
((char **) \
        (&(bufferdata)->bd_flexdata + 3*(nop)))
#define NBF_REDUCE_OUTERSIZE (   bufferdata)    ((bufferdata)->reduce_outersize)

Referenced by npyiter_coalesce_axes().

#define NBF_REDUCE_OUTERSTRIDES (   bufferdata)
Value:
( \
        (&(bufferdata)->bd_flexdata + 2*(nop)))
#define NBF_REDUCE_POS (   bufferdata)    ((bufferdata)->reduce_pos)
#define NBF_SIZE (   bufferdata)    ((bufferdata)->size)
#define NBF_STRIDES (   bufferdata)
Value:
( \
        &(bufferdata)->bd_flexdata + 0)

Referenced by NpyIter_GotoIndex().

#define NBF_WRITETRANSFERDATA (   bufferdata)
Value:
((NpyAuxData **) \
        (&(bufferdata)->bd_flexdata + 7*(nop)))

Referenced by NpyIter_Copy().

#define NBF_WRITETRANSFERFN (   bufferdata)
Value:
((PyArray_StridedTransferFn **) \
        (&(bufferdata)->bd_flexdata + 6*(nop)))
#define NIT_ADVANCE_AXISDATA (   axisdata,
  count 
)    axisdata = NIT_INDEX_AXISDATA(axisdata, count)
#define NIT_AXISDATA (   iter)
Value:
((NpyIter_AxisData *)( \
        &(iter)->iter_flexdata + NIT_AXISDATA_OFFSET(itflags, ndim, nop)))

Referenced by npyiter_flip_negative_strides(), and NpyIter_GetIndexPtr().

#define NIT_AXISDATA_OFFSET (   itflags,
  ndim,
  nop 
)
Value:
(NIT_BUFFERDATA_OFFSET(itflags, ndim, nop) + \
         NIT_BUFFERDATA_SIZEOF(itflags, ndim, nop))
#define NIT_AXISDATA_SIZEOF (   itflags,
  ndim,
  nop 
)
Value:
(( \ \
        1 + \ \
        1 + \ \
        2*((nop)+1) \
        )*NPY_SIZEOF_INTP )
Size of one AXISDATA struct within the iterator

Referenced by npyiter_flip_negative_strides().

#define NIT_BASEOFFSETS (   iter)
Value:
((npy_intp *)( \
        &(iter)->iter_flexdata + NIT_BASEOFFSETS_OFFSET(itflags, ndim, nop)))

Referenced by NpyIter_GetAxisStrideArray().

#define NIT_BASEOFFSETS_OFFSET (   itflags,
  ndim,
  nop 
)
Value:
(NIT_RESETDATAPTR_OFFSET(itflags, ndim, nop) + \
         NIT_RESETDATAPTR_SIZEOF(itflags, ndim, nop))
#define NIT_BASEOFFSETS_SIZEOF (   itflags,
  ndim,
  nop 
)    ((NPY_SIZEOF_INTP)*(nop+1))
#define NIT_BUFFERDATA (   iter)
#define NIT_BUFFERDATA_OFFSET (   itflags,
  ndim,
  nop 
)
Value:
(NIT_OPITFLAGS_OFFSET(itflags, ndim, nop) + \
         NIT_OPITFLAGS_SIZEOF(itflags, ndim, nop))
#define NIT_BUFFERDATA_SIZEOF (   itflags,
  ndim,
  nop 
)    ((itflags&NPY_ITFLAG_BUFFER) ? ((NPY_SIZEOF_INTP)*(6 + 9*nop)) : 0)
#define NIT_DTYPES (   iter)
Value:
((PyArray_Descr **)( \
        &(iter)->iter_flexdata + NIT_DTYPES_OFFSET(itflags, ndim, nop)))

Referenced by NpyIter_Copy().

#define NIT_DTYPES_OFFSET (   itflags,
  ndim,
  nop 
)
Value:
(NIT_PERM_OFFSET() + \
         NIT_PERM_SIZEOF(itflags, ndim, nop))
#define NIT_DTYPES_SIZEOF (   itflags,
  ndim,
  nop 
)    ((NPY_SIZEOF_INTP)*(nop))
#define NIT_INDEX_AXISDATA (   axisdata,
  index 
)
Value:
((NpyIter_AxisData *) \
        (((char *)(axisdata)) + (index)*sizeof_axisdata))
Macro to advance an AXISDATA pointer by a specified count. Requires that sizeof_axisdata be previously initialized to NIT_AXISDATA_SIZEOF(itflags, ndim, nop).
#define NIT_ITEREND (   iter)    (iter->iterend)
#define NIT_ITERINDEX (   iter)    (iter->iterindex)
#define NIT_ITERSIZE (   iter)    (iter->itersize)
#define NIT_ITERSTART (   iter)    (iter->iterstart)
#define NIT_ITFLAGS (   iter)    ((iter)->itflags)
#define NIT_MASKOP (   iter)    ((iter)->maskop)
#define NIT_NDIM (   iter)    ((iter)->ndim)
#define NIT_OPERANDS (   iter)
Value:
((PyArrayObject **)( \
        &(iter)->iter_flexdata + NIT_OPERANDS_OFFSET(itflags, ndim, nop)))

Referenced by NpyIter_Copy(), and NpyIter_GetShape().

#define NIT_OPERANDS_OFFSET (   itflags,
  ndim,
  nop 
)
Value:
(NIT_BASEOFFSETS_OFFSET(itflags, ndim, nop) + \
         NIT_BASEOFFSETS_SIZEOF(itflags, ndim, nop))
#define NIT_OPERANDS_SIZEOF (   itflags,
  ndim,
  nop 
)    ((NPY_SIZEOF_INTP)*(nop))
#define NIT_OPITFLAGS (   iter)
Value:
( \
        &(iter)->iter_flexdata + NIT_OPITFLAGS_OFFSET(itflags, ndim, nop))

Referenced by NpyIter_GetDataPtrArray().

#define NIT_OPITFLAGS_OFFSET (   itflags,
  ndim,
  nop 
)
Value:
(NIT_OPERANDS_OFFSET(itflags, ndim, nop) + \
         NIT_OPERANDS_SIZEOF(itflags, ndim, nop))
#define NIT_OPITFLAGS_SIZEOF (   itflags,
  ndim,
  nop 
)    (NPY_INTP_ALIGNED(nop))
#define NIT_PERM (   iter)
Value:
((npy_int8 *)( \
        &(iter)->iter_flexdata + NIT_PERM_OFFSET()))

Referenced by npyiter_flip_negative_strides().

#define NIT_PERM_OFFSET ( )    (0)
Byte offsets of the iterator members starting from iter->iter_flexdata
#define NIT_PERM_SIZEOF (   itflags,
  ndim,
  nop 
)    NPY_INTP_ALIGNED(NPY_MAXDIMS)
Byte sizes of the iterator members
#define NIT_RESETDATAPTR (   iter)
Value:
((char **)( \
        &(iter)->iter_flexdata + NIT_RESETDATAPTR_OFFSET(itflags, ndim, nop)))

Referenced by NpyIter_GetIterIndexRange().

#define NIT_RESETDATAPTR_OFFSET (   itflags,
  ndim,
  nop 
)
Value:
(NIT_DTYPES_OFFSET(itflags, ndim, nop) + \
         NIT_DTYPES_SIZEOF(itflags, ndim, nop))
#define NIT_RESETDATAPTR_SIZEOF (   itflags,
  ndim,
  nop 
)    ((NPY_SIZEOF_INTP)*(nop+1))
#define NIT_SIZEOF_ITERATOR (   itflags,
  ndim,
  nop 
)
Value:
Size of the whole iterator
#define NPY_INTP_ALIGNED (   size)    ((size + 0x7)&(-0x8))
System Message: ERROR/3 (<string>, line 1) Document or section may not begin with a transition.

System Message: ERROR/3 (<string>, line 1) Document may not end with a transition.
Rounds up a number of bytes to be divisible by sizeof intp
#define NPY_IT_CONSTRUCTION_TIMING   0
**** ITERATOR CONSTRUCTION TIMING *********
#define NPY_IT_DBG_PRINT (   s)
#define NPY_IT_DBG_PRINT1 (   s,
  p1 
)
#define NPY_IT_DBG_PRINT2 (   s,
  p1,
  p2 
)

Referenced by npyiter_coalesce_axes().

#define NPY_IT_DBG_PRINT3 (   s,
  p1,
  p2,
  p3 
)
#define NPY_IT_DBG_TRACING   0
System Message: ERROR/3 (<string>, line 1) Document or section may not begin with a transition.

System Message: ERROR/3 (<string>, line 1) Document may not end with a transition.
**** PRINTF DEBUG TRACING *********
#define NPY_IT_TIME_POINT (   var)
#define NPY_ITFLAG_BUFFER   0x0080
The iterator is buffered
#define NPY_ITFLAG_DELAYBUF   0x0400
Delay buffer allocation until first Reset* call

Referenced by NpyIter_EnableExternalLoop().

#define NPY_ITFLAG_EXLOOP   0x0020
The inner loop is handled outside the iterator
#define NPY_ITFLAG_FORCEDORDER   0x0010
The iteration order was forced on construction
#define NPY_ITFLAG_GROWINNER   0x0100
The iterator should grow the buffered inner loop when possible
#define NPY_ITFLAG_HASINDEX   0x0004
The iterator is tracking an index
#define NPY_ITFLAG_HASMULTIINDEX   0x0008
The iterator is tracking a multi-index
#define NPY_ITFLAG_IDENTPERM   0x0001
Internal iterator flags
The perm is the identity
#define NPY_ITFLAG_NEEDSAPI   0x0800
Iteration needs API access during iternext
#define NPY_ITFLAG_NEGPERM   0x0002
The perm has negative entries (indicating flipped axes)
#define NPY_ITFLAG_ONEITERATION   0x0200
There is just one iteration, can specialize iternext for that
#define NPY_ITFLAG_RANGE   0x0040
The iterator is ranged
#define NPY_ITFLAG_REDUCE   0x1000
Iteration includes one or more operands being reduced

Referenced by NpyIter_GotoIndex().

#define NPY_ITFLAG_REUSE_REDUCE_LOOPS   0x2000
Reduce iteration doesn't need to recalculate reduce loops next time
#define NPY_NO_DEPRECATED_API
#define NPY_OP_ITFLAG_ALIGNED   0x10
The operand is aligned
#define NPY_OP_ITFLAG_BUFNEVER   0x08
The operand never needs buffering
#define NPY_OP_ITFLAG_CAST   0x04
The operand needs type conversion/byte swapping/alignment
#define NPY_OP_ITFLAG_READ   0x02
The operand will be read from
#define NPY_OP_ITFLAG_REDUCE   0x20
The operand is being reduced
#define NPY_OP_ITFLAG_VIRTUAL   0x40
The operand is for temporary use, does not have a backing array
#define NPY_OP_ITFLAG_WRITE   0x01
Internal iterator per-operand iterator flags
The operand will be written to

Referenced by NpyIter_GetDataPtrArray().

#define NPY_OP_ITFLAG_WRITEMASKED   0x80
The operand requires masking when copying buffer -> array

Referenced by npyiter_coalesce_axes().

#define PY_SSIZE_T_CLEAN

Typedef Documentation

typedef struct NpyIter_AD NpyIter_AxisData

Function Documentation

NPY_NO_EXPORT int npyiter_allocate_buffers ( NpyIter iter,
char **  errmsg 
)
If errmsg is non-NULL, it should point to a variable which will receive the error message, and no Python exception will be set. This is so that the function can be called from code not holding the GIL.

npy_uint32 itflags = NIT_ITFLAGS(iter);
int ndim = NIT_NDIM(iter);
If we have determined that a buffer may be needed, allocate one.

Referenced by NpyIter_EnableExternalLoop().

NPY_NO_EXPORT void npyiter_coalesce_axes ( NpyIter iter)
Internal helper functions shared between implementation files

The HASMULTIINDEX or IDENTPERM flags do not apply after coalescing
Check that all the axes can be coalesced
If the number of axes shrunk, reset the perm and compress the data into the new layout.
Reset to an identity perm

References NAD_INDEX, NAD_SHAPE, NAD_STRIDES, NBF_REDUCE_OUTERSIZE, NBF_SIZE, NPY_IT_DBG_PRINT1, NPY_IT_DBG_PRINT2, NPY_OP_ITFLAG_WRITEMASKED, and PyArray_TransferMaskedStridedToNDim().

NPY_NO_EXPORT void npyiter_copy_from_buffers ( NpyIter iter)
This gets called after the the buffers have been exhausted, and their data needs to be written back to the arrays. The multi-index must be positioned for the beginning of the buffer.

If we're past the end, nothing to copy
Copy the data back to the arrays. If the type has refs, this function moves them so the buffer's refs are released.
Copy back only if the pointer was pointing to the buffer
If this operand is being reduced in the inner loop, its buffering stride was set to zero, and just one element was copied.
The mask pointer may be in the buffer or in the array, detect which one.
If there's no copy back, we may have to decrement refs. In this case, the transfer function has a 'decsrcref' transfer function, so we can use it to do the decrement.
Decrement refs only if the pointer was pointing to the buffer
Decrement refs
Zero out the memory for safety. For instance, if during iteration some Python code copied an array pointing into the buffer, it will get None values for its references after this.

Referenced by NpyIter_EnableExternalLoop(), and NpyIter_GotoIndex().

NPY_NO_EXPORT void npyiter_copy_to_buffers ( NpyIter iter,
char **  prev_dataptrs 
)
This gets called after the iterator has been positioned to a multi-index for the start of a buffer. It decides which operands need a buffer, and copies the data into the buffers.

Have to get this flag before npyiter_checkreducesize sets it for the next iteration.
Calculate the size if using any buffers
If last time around, the reduce loop structure was full, we reuse it
Try to do make the outersize as big as possible. This allows it to shrink when processing the last bit of the outer reduce loop, then grow again at the beginnning of the next outer reduce loop.
If the full transfer size doesn't fit in the buffer, truncate it
If there are any reduction operands, we may have to make the size smaller so we don't copy the same value into a buffer twice, as the buffering does not have a mechanism to combine values itself.
Calculate the maximum size if using a single stride and no buffers
If the buffer is write-only, these two are NULL, and the buffer pointers will be set up but the read copy won't be done
Never need to buffer this operand
Should not adjust the stride - ad_strides[iop] could be zero, but strides[iop] was initialized to the first non-trivial stride.
Never need to buffer this operand
Should not adjust the stride - ad_strides[iop] could be zero, but strides[iop] was initialized to the first non-trivial stride.
Just a copy
No copyswap or cast was requested, so all we're doing is copying the data to fill the buffer and produce a single stride. If the underlying data already does that, no need to copy it.
If some other op is reduced, we have a double reduce loop
In this case, the buffer is being used
Just a copy, but with a reduction
It's all in one stride in the inner loop dimension
It's all in one stride in the reduce outer loop
Outer reduce loop advances by one item
In this case, the buffer is being used
Both outer and inner reduce loops have stride 0
Outer reduce loop advances by one item
It's all in one stride in the reduce outer loop
Outer reduce loop advances by one item
In this case, the buffer is being used
Reduction in outer reduce loop
Advance to next items in outer reduce loop
In this case, the buffer is always being used
The buffer is being used with reduction
Both outer and inner reduce loops have stride 0
Outer reduce loop advances by one item
Reduction in outer reduce loop
Advance to next items in outer reduce loop
If stransfer wasn't set to NULL, buffering is required
If this operand is being reduced in the inner loop, set its buffering stride to zero, and just copy one element.
When we're reducing a single element, and it's still the same element, don't overwrite it even when reuse reduce loops is unset. This preserves the precision of the intermediate calculation.
If the whole buffered loop structure remains the same, and the source pointer for this data didn't change, we don't have to copy the data again.
If the data type requires zero-inititialization
Can't skip the transfer in this case
If the data type requires zero-inititialization
If buffering wasn't needed, we can grow the inner loop to as large as possible.
TODO: Could grow REDUCE loop too with some more logic above.

References _PyArray_Descr::elsize, and NPY_IT_DBG_PRINT1.

Referenced by NpyIter_EnableExternalLoop(), NpyIter_GotoIndex(), and NpyIter_New().

NPY_NO_EXPORT void npyiter_goto_iterindex ( NpyIter iter,
npy_intp  iterindex 
)
This sets the AXISDATA portion of the iterator to the specified iterindex, updating the pointers as well. This function does no error checking.

Set the multi-index, from the fastest-changing to the slowest-changing.
Accumulate the successive pointers with their offsets in the opposite order, starting from the original data pointers.

Referenced by NpyIter_EnableExternalLoop(), NpyIter_GotoIndex(), and NpyIter_New().