numpy  2.0.0
src/private/lowlevel_strided_loops.h File Reference
#include "common.h"
#include <npy_config.h>

Go to the source code of this file.

Defines

#define NPY_RAW_ITER_START(idim, ndim, coord, shape)
#define NPY_RAW_ITER_ONE_NEXT(idim, ndim, coord, shape, data, strides)
#define NPY_RAW_ITER_TWO_NEXT(idim, ndim, coord, shape, dataA, stridesA, dataB, stridesB)
#define NPY_RAW_ITER_THREE_NEXT(idim, ndim, coord, shape, dataA, stridesA, dataB, stridesB, dataC, stridesC)
#define NPY_RAW_ITER_FOUR_NEXT(idim, ndim, coord, shape, dataA, stridesA, dataB, stridesB, dataC, stridesC, dataD, stridesD)
#define PyArray_EQUIVALENTLY_ITERABLE(arr1, arr2)
#define PyArray_TRIVIALLY_ITERABLE(arr)
#define PyArray_PREPARE_TRIVIAL_ITERATION(arr, count, data, stride)
#define PyArray_TRIVIALLY_ITERABLE_PAIR(arr1, arr2)
#define PyArray_PREPARE_TRIVIAL_PAIR_ITERATION(arr1, arr2, count, data1, data2, stride1, stride2)
#define PyArray_TRIVIALLY_ITERABLE_TRIPLE(arr1, arr2, arr3)
#define PyArray_PREPARE_TRIVIAL_TRIPLE_ITERATION(arr1, arr2, arr3, count, data1, data2, data3, stride1, stride2, stride3)

Typedefs

typedef void( PyArray_StridedUnaryOp )(char *dst, npy_intp dst_stride, char *src, npy_intp src_stride, npy_intp N, npy_intp src_itemsize, NpyAuxData *transferdata)
typedef void( PyArray_MaskedStridedUnaryOp )(char *dst, npy_intp dst_stride, char *src, npy_intp src_stride, npy_bool *mask, npy_intp mask_stride, npy_intp N, npy_intp src_itemsize, NpyAuxData *transferdata)
typedef void( PyArray_StridedBinaryOp )(char *dst, npy_intp dst_stride, char *src0, npy_intp src0_stride, char *src1, npy_intp src1_stride, npy_intp N, NpyAuxData *transferdata)

Functions

NPY_NO_EXPORT
PyArray_StridedUnaryOp
PyArray_GetStridedCopyFn (int aligned, npy_intp src_stride, npy_intp dst_stride, npy_intp itemsize)
NPY_NO_EXPORT
PyArray_StridedUnaryOp
PyArray_GetStridedCopySwapFn (int aligned, npy_intp src_stride, npy_intp dst_stride, npy_intp itemsize)
NPY_NO_EXPORT
PyArray_StridedUnaryOp
PyArray_GetStridedCopySwapPairFn (int aligned, npy_intp src_stride, npy_intp dst_stride, npy_intp itemsize)
NPY_NO_EXPORT int PyArray_GetStridedZeroPadCopyFn (int aligned, int unicode_swap, npy_intp src_stride, npy_intp dst_stride, npy_intp src_itemsize, npy_intp dst_itemsize, PyArray_StridedUnaryOp **outstransfer, NpyAuxData **outtransferdata)
NPY_NO_EXPORT
PyArray_StridedUnaryOp
PyArray_GetStridedNumericCastFn (int aligned, npy_intp src_stride, npy_intp dst_stride, int src_type_num, int dst_type_num)
NPY_NO_EXPORT int PyArray_GetDTypeCopySwapFn (int aligned, npy_intp src_stride, npy_intp dst_stride, PyArray_Descr *dtype, PyArray_StridedUnaryOp **outstransfer, NpyAuxData **outtransferdata)
NPY_NO_EXPORT int PyArray_GetDTypeTransferFunction (int aligned, npy_intp src_stride, npy_intp dst_stride, PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype, int move_references, PyArray_StridedUnaryOp **out_stransfer, NpyAuxData **out_transferdata, int *out_needs_api)
NPY_NO_EXPORT int PyArray_GetMaskedDTypeTransferFunction (int aligned, npy_intp src_stride, npy_intp dst_stride, npy_intp mask_stride, PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype, PyArray_Descr *mask_dtype, int move_references, PyArray_MaskedStridedUnaryOp **out_stransfer, NpyAuxData **out_transferdata, int *out_needs_api)
NPY_NO_EXPORT int PyArray_CastRawArrays (npy_intp count, char *src, char *dst, npy_intp src_stride, npy_intp dst_stride, PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype, int move_references)
NPY_NO_EXPORT npy_intp PyArray_TransferNDimToStrided (npy_intp ndim, char *dst, npy_intp dst_stride, char *src, npy_intp *src_strides, npy_intp src_strides_inc, npy_intp *coords, npy_intp coords_inc, npy_intp *shape, npy_intp shape_inc, npy_intp count, npy_intp src_itemsize, PyArray_StridedUnaryOp *stransfer, NpyAuxData *transferdata)
NPY_NO_EXPORT npy_intp PyArray_TransferStridedToNDim (npy_intp ndim, char *dst, npy_intp *dst_strides, npy_intp dst_strides_inc, char *src, npy_intp src_stride, npy_intp *coords, npy_intp coords_inc, npy_intp *shape, npy_intp shape_inc, npy_intp count, npy_intp src_itemsize, PyArray_StridedUnaryOp *stransfer, NpyAuxData *transferdata)
NPY_NO_EXPORT npy_intp PyArray_TransferMaskedStridedToNDim (npy_intp ndim, char *dst, npy_intp *dst_strides, npy_intp dst_strides_inc, char *src, npy_intp src_stride, npy_bool *mask, npy_intp mask_stride, npy_intp *coords, npy_intp coords_inc, npy_intp *shape, npy_intp shape_inc, npy_intp count, npy_intp src_itemsize, PyArray_MaskedStridedUnaryOp *stransfer, NpyAuxData *data)
NPY_NO_EXPORT int mapiter_trivial_get (PyArrayObject *self, PyArrayObject *ind, PyArrayObject *result)
NPY_NO_EXPORT int mapiter_trivial_set (PyArrayObject *self, PyArrayObject *ind, PyArrayObject *result)
NPY_NO_EXPORT int mapiter_get (PyArrayMapIterObject *mit)
NPY_NO_EXPORT int mapiter_set (PyArrayMapIterObject *mit)
NPY_NO_EXPORT int PyArray_PrepareOneRawArrayIter (int ndim, npy_intp *shape, char *data, npy_intp *strides, int *out_ndim, npy_intp *out_shape, char **out_data, npy_intp *out_strides)
NPY_NO_EXPORT int PyArray_PrepareTwoRawArrayIter (int ndim, npy_intp *shape, char *dataA, npy_intp *stridesA, char *dataB, npy_intp *stridesB, int *out_ndim, npy_intp *out_shape, char **out_dataA, npy_intp *out_stridesA, char **out_dataB, npy_intp *out_stridesB)
NPY_NO_EXPORT int PyArray_PrepareThreeRawArrayIter (int ndim, npy_intp *shape, char *dataA, npy_intp *stridesA, char *dataB, npy_intp *stridesB, char *dataC, npy_intp *stridesC, int *out_ndim, npy_intp *out_shape, char **out_dataA, npy_intp *out_stridesA, char **out_dataB, npy_intp *out_stridesB, char **out_dataC, npy_intp *out_stridesC)
static NPY_INLINE npy_uintp npy_aligned_block_offset (const void *addr, const npy_uintp esize, const npy_uintp alignment, const npy_uintp nvals)
static NPY_INLINE npy_uintp npy_blocked_end (const npy_uintp offset, const npy_uintp esize, const npy_uintp vsz, const npy_uintp nvals)
static NPY_INLINE npy_uint16 npy_bswap2 (npy_uint16 x)
static NPY_INLINE void npy_bswap2_unaligned (char *x)
static NPY_INLINE npy_uint32 npy_bswap4 (npy_uint32 x)
static NPY_INLINE void npy_bswap4_unaligned (char *x)
static NPY_INLINE npy_uint64 npy_bswap8 (npy_uint64 x)
static NPY_INLINE void npy_bswap8_unaligned (char *x)

Define Documentation

#define NPY_RAW_ITER_FOUR_NEXT (   idim,
  ndim,
  coord,
  shape,
  dataA,
  stridesA,
  dataB,
  stridesB,
  dataC,
  stridesC,
  dataD,
  stridesD 
)
Value:
for ((idim) = 1; (idim) < (ndim); ++(idim)) { \
                if (++(coord)[idim] == (shape)[idim]) { \
                    (coord)[idim] = 0; \
                    (dataA) -= ((shape)[idim] - 1) * (stridesA)[idim]; \
                    (dataB) -= ((shape)[idim] - 1) * (stridesB)[idim]; \
                    (dataC) -= ((shape)[idim] - 1) * (stridesC)[idim]; \
                    (dataD) -= ((shape)[idim] - 1) * (stridesD)[idim]; \
                } \
                else { \
                    (dataA) += (stridesA)[idim]; \
                    (dataB) += (stridesB)[idim]; \
                    (dataC) += (stridesC)[idim]; \
                    (dataD) += (stridesD)[idim]; \
                    break; \
                } \
            } \
        } while ((idim) < (ndim))
Increment to the next n-dimensional coordinate for four raw arrays
#define NPY_RAW_ITER_ONE_NEXT (   idim,
  ndim,
  coord,
  shape,
  data,
  strides 
)
Value:
for ((idim) = 1; (idim) < (ndim); ++(idim)) { \
                if (++(coord)[idim] == (shape)[idim]) { \
                    (coord)[idim] = 0; \
                    (data) -= ((shape)[idim] - 1) * (strides)[idim]; \
                } \
                else { \
                    (data) += (strides)[idim]; \
                    break; \
                } \
            } \
        } while ((idim) < (ndim))
Increment to the next n-dimensional coordinate for one raw array

Referenced by raw_array_assign_scalar().

#define NPY_RAW_ITER_START (   idim,
  ndim,
  coord,
  shape 
)
Value:
memset((coord), 0, (ndim) * sizeof(coord[0])); \
        do {
Start raw iteration

Referenced by raw_array_assign_array(), and raw_array_assign_scalar().

#define NPY_RAW_ITER_THREE_NEXT (   idim,
  ndim,
  coord,
  shape,
  dataA,
  stridesA,
  dataB,
  stridesB,
  dataC,
  stridesC 
)
Value:
for ((idim) = 1; (idim) < (ndim); ++(idim)) { \
                if (++(coord)[idim] == (shape)[idim]) { \
                    (coord)[idim] = 0; \
                    (dataA) -= ((shape)[idim] - 1) * (stridesA)[idim]; \
                    (dataB) -= ((shape)[idim] - 1) * (stridesB)[idim]; \
                    (dataC) -= ((shape)[idim] - 1) * (stridesC)[idim]; \
                } \
                else { \
                    (dataA) += (stridesA)[idim]; \
                    (dataB) += (stridesB)[idim]; \
                    (dataC) += (stridesC)[idim]; \
                    break; \
                } \
            } \
        } while ((idim) < (ndim))
Increment to the next n-dimensional coordinate for three raw arrays
#define NPY_RAW_ITER_TWO_NEXT (   idim,
  ndim,
  coord,
  shape,
  dataA,
  stridesA,
  dataB,
  stridesB 
)
Value:
for ((idim) = 1; (idim) < (ndim); ++(idim)) { \
                if (++(coord)[idim] == (shape)[idim]) { \
                    (coord)[idim] = 0; \
                    (dataA) -= ((shape)[idim] - 1) * (stridesA)[idim]; \
                    (dataB) -= ((shape)[idim] - 1) * (stridesB)[idim]; \
                } \
                else { \
                    (dataA) += (stridesA)[idim]; \
                    (dataB) += (stridesB)[idim]; \
                    break; \
                } \
            } \
        } while ((idim) < (ndim))
Increment to the next n-dimensional coordinate for two raw arrays

Referenced by raw_array_assign_array().

#define PyArray_EQUIVALENTLY_ITERABLE (   arr1,
  arr2 
)
Value:
( \
                        PyArray_NDIM(arr1) == PyArray_NDIM(arr2) && \
                        PyArray_CompareLists(PyArray_DIMS(arr1), \
                                             PyArray_DIMS(arr2), \
                                             PyArray_NDIM(arr1)) && \
                        (PyArray_FLAGS(arr1)&(NPY_ARRAY_C_CONTIGUOUS| \
                                      NPY_ARRAY_F_CONTIGUOUS)) & \
                                (PyArray_FLAGS(arr2)&(NPY_ARRAY_C_CONTIGUOUS| \
                                              NPY_ARRAY_F_CONTIGUOUS)) \
                        )
<blockquote> TRIVIAL ITERATION</blockquote>
In some cases when the iteration order isn't important, iteration over arrays is trivial. This is the case when:

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

<blockquote>

  • The array has 0 or 1 dimensions.
  • The array is C or Fortran contiguous.

</blockquote>

System Message: WARNING/2 (<string>, line 7) Block quote ends without a blank line; unexpected unindent.
Use of an iterator can be skipped when this occurs. These macros assist in detecting and taking advantage of the situation. Note that it may be worthwhile to further check if the stride is a contiguous stride and take advantage of that.
Here is example code for a single array: <blockquote>

if (PyArray_TRIVIALLY_ITERABLE(self) {

char *data; npy_intp count, stride;

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

PyArray_PREPARE_TRIVIAL_ITERATION(self, count, data, stride);

while (count--) {

// Use the data pointer

data += stride;

System Message: WARNING/2 (<string>, line 24) Definition list ends without a blank line; unexpected unindent.

}

System Message: WARNING/2 (<string>, line 25) Definition list ends without a blank line; unexpected unindent.
} else {

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

<blockquote> Create iterator, etc...</blockquote>

System Message: WARNING/2 (<string>, line 28) Block quote ends without a blank line; unexpected unindent.
} </blockquote>
Here is example code for a pair of arrays: <blockquote>

if (PyArray_TRIVIALLY_ITERABLE_PAIR(a1, a2) {

char *data1, *data2; npy_intp count, stride1, stride2;

System Message: WARNING/2 (<string>, line 33); backlink Inline emphasis start-string without end-string.
System Message: WARNING/2 (<string>, line 33); backlink Inline emphasis start-string without end-string.
PyArray_PREPARE_TRIVIAL_PAIR_ITERATION(a1, a2, count,
data1, data2, stride1, stride2);
while (count--) {

// Use the data1 and data2 pointers

data1 += stride1; data2 += stride2;

System Message: WARNING/2 (<string>, line 44) Definition list ends without a blank line; unexpected unindent.

}

System Message: WARNING/2 (<string>, line 45) Definition list ends without a blank line; unexpected unindent.
} else {

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

<blockquote> Create iterator, etc...</blockquote>

System Message: WARNING/2 (<string>, line 48) Block quote ends without a blank line; unexpected unindent.
} </blockquote>
Note: Equivalently iterable macro requires one of arr1 or arr2 be
trivially iterable to be valid.
#define PyArray_PREPARE_TRIVIAL_ITERATION (   arr,
  count,
  data,
  stride 
)
Value:
count = PyArray_SIZE(arr); \
                    data = PyArray_BYTES(arr); \
                    stride = ((PyArray_NDIM(arr) == 0) ? 0 : \
                                    ((PyArray_NDIM(arr) == 1) ? \
                                            PyArray_STRIDE(arr, 0) : \
                                            PyArray_ITEMSIZE(arr)));

Referenced by _nonzero_indices().

#define PyArray_PREPARE_TRIVIAL_PAIR_ITERATION (   arr1,
  arr2,
  count,
  data1,
  data2,
  stride1,
  stride2 
)
Value:
{ \
                    npy_intp size1 = PyArray_SIZE(arr1); \
                    npy_intp size2 = PyArray_SIZE(arr2); \
                    count = ((size1 > size2) || size1 == 0) ? size1 : size2; \
                    data1 = PyArray_BYTES(arr1); \
                    data2 = PyArray_BYTES(arr2); \
                    stride1 = (size1 == 1 ? 0 : ((PyArray_NDIM(arr1) == 1) ? \
                                                PyArray_STRIDE(arr1, 0) : \
                                                PyArray_ITEMSIZE(arr1))); \
                    stride2 = (size2 == 1 ? 0 : ((PyArray_NDIM(arr2) == 1) ? \
                                                PyArray_STRIDE(arr2, 0) : \
                                                PyArray_ITEMSIZE(arr2))); \
                }
#define PyArray_PREPARE_TRIVIAL_TRIPLE_ITERATION (   arr1,
  arr2,
  arr3,
  count,
  data1,
  data2,
  data3,
  stride1,
  stride2,
  stride3 
)
Value:
{ \
                    npy_intp size1 = PyArray_SIZE(arr1); \
                    npy_intp size2 = PyArray_SIZE(arr2); \
                    npy_intp size3 = PyArray_SIZE(arr3); \
                    count = ((size1 > size2) || size1 == 0) ? size1 : size2; \
                    count = ((size3 > count) || size3 == 0) ? size3 : count; \
                    data1 = PyArray_BYTES(arr1); \
                    data2 = PyArray_BYTES(arr2); \
                    data3 = PyArray_BYTES(arr3); \
                    stride1 = (size1 == 1 ? 0 : ((PyArray_NDIM(arr1) == 1) ? \
                                                PyArray_STRIDE(arr1, 0) : \
                                                PyArray_ITEMSIZE(arr1))); \
                    stride2 = (size2 == 1 ? 0 : ((PyArray_NDIM(arr2) == 1) ? \
                                                PyArray_STRIDE(arr2, 0) : \
                                                PyArray_ITEMSIZE(arr2))); \
                    stride3 = (size3 == 1 ? 0 : ((PyArray_NDIM(arr3) == 1) ? \
                                                PyArray_STRIDE(arr3, 0) : \
                                                PyArray_ITEMSIZE(arr3))); \
                }
#define PyArray_TRIVIALLY_ITERABLE (   arr)
Value:
( \
                    PyArray_NDIM(arr) <= 1 || \
                    PyArray_CHKFLAGS(arr, NPY_ARRAY_C_CONTIGUOUS) || \
                    PyArray_CHKFLAGS(arr, NPY_ARRAY_F_CONTIGUOUS) \
                    )

Referenced by prepare_ufunc_output().

#define PyArray_TRIVIALLY_ITERABLE_PAIR (   arr1,
  arr2 
)
Value:
(\
                    PyArray_TRIVIALLY_ITERABLE(arr1) && \
                        (PyArray_NDIM(arr2) == 0 || \
                         PyArray_EQUIVALENTLY_ITERABLE(arr1, arr2) || \
                         (PyArray_NDIM(arr1) == 0 && \
                             PyArray_TRIVIALLY_ITERABLE(arr2) \
                         ) \
                        ) \
                    )
#define PyArray_TRIVIALLY_ITERABLE_TRIPLE (   arr1,
  arr2,
  arr3 
)
Value:
(\
                PyArray_TRIVIALLY_ITERABLE(arr1) && \
                    ((PyArray_NDIM(arr2) == 0 && \
                        (PyArray_NDIM(arr3) == 0 || \
                            PyArray_EQUIVALENTLY_ITERABLE(arr1, arr3) \
                        ) \
                     ) || \
                     (PyArray_EQUIVALENTLY_ITERABLE(arr1, arr2) && \
                        (PyArray_NDIM(arr3) == 0 || \
                            PyArray_EQUIVALENTLY_ITERABLE(arr1, arr3) \
                        ) \
                     ) || \
                     (PyArray_NDIM(arr1) == 0 && \
                        PyArray_TRIVIALLY_ITERABLE(arr2) && \
                            (PyArray_NDIM(arr3) == 0 || \
                                PyArray_EQUIVALENTLY_ITERABLE(arr2, arr3) \
                            ) \
                     ) \
                    ) \
                )

Typedef Documentation

typedef void( PyArray_MaskedStridedUnaryOp)(char *dst, npy_intp dst_stride, char *src, npy_intp src_stride, npy_bool *mask, npy_intp mask_stride, npy_intp N, npy_intp src_itemsize, NpyAuxData *transferdata)
This is for pointers to functions which behave exactly as for PyArray_StridedUnaryOp, but with an additional mask controlling which values are transformed.
In particular, the 'i'-th element is operated on if and only if mask[i*mask_stride] is true.
typedef void( PyArray_StridedBinaryOp)(char *dst, npy_intp dst_stride, char *src0, npy_intp src0_stride, char *src1, npy_intp src1_stride, npy_intp N, NpyAuxData *transferdata)
This function pointer is for binary operations that input two arbitrarily strided one-dimensional array segments and output an arbitrarily strided array segment of the same size. It may be a fully general function, or a specialized function when the strides or item size have particular known values.
Examples of binary operations are the basic arithmetic operations, logical operators AND, OR, and many others.
The 'transferdata' parameter is slightly special, following a generic auxiliary data pattern defined in ndarraytypes.h Use NPY_AUXDATA_CLONE and NPY_AUXDATA_FREE to deal with this data.
typedef void( PyArray_StridedUnaryOp)(char *dst, npy_intp dst_stride, char *src, npy_intp src_stride, npy_intp N, npy_intp src_itemsize, NpyAuxData *transferdata)
NOTE: This API should remain private for the time being, to allow
for further refinement. I think the 'aligned' mechanism needs changing, for example.
This function pointer is for unary operations that input an arbitrarily strided one-dimensional array segment and output an arbitrarily strided array segment of the same size. It may be a fully general function, or a specialized function when the strides or item size have particular known values.
Examples of unary operations are a straight copy, a byte-swap, and a casting operation,
The 'transferdata' parameter is slightly special, following a generic auxiliary data pattern defined in ndarraytypes.h Use NPY_AUXDATA_CLONE and NPY_AUXDATA_FREE to deal with this data.

Function Documentation

static NPY_INLINE npy_uintp npy_aligned_block_offset ( const void *  addr,
const npy_uintp  esize,
const npy_uintp  alignment,
const npy_uintp  nvals 
) [static]
Return number of elements that must be peeled from the start of 'addr' with 'nvals' elements of size 'esize' in order to reach 'alignment'. alignment must be a power of two. see npy_blocked_end for an example
static NPY_INLINE npy_uintp npy_blocked_end ( const npy_uintp  offset,
const npy_uintp  esize,
const npy_uintp  vsz,
const npy_uintp  nvals 
) [static]
Return upper loop bound for an array of 'nvals' elements of size 'esize' peeled by 'offset' elements and blocking to a vector size of 'vsz' in bytes
example usage: npy_intp i; double v[101]; npy_intp esize = sizeof(v[0]); npy_intp peel = npy_aligned_block_offset(v, esize, 16, n); peel to alignment 16 for (i = 0; i < peel; i++)

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

<blockquote> <scalar-op></blockquote>

System Message: WARNING/2 (<string>, line 13) Block quote ends without a blank line; unexpected unindent.
// simd vectorized operation for (; i < npy_blocked_end(peel, esize, 16, n); i += 16 / esize)

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

<blockquote> <blocked-op></blockquote>

System Message: WARNING/2 (<string>, line 16) Block quote ends without a blank line; unexpected unindent.
// handle scalar rest for(; i < n; i++)

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

<blockquote> <scalar-op></blockquote>

static NPY_INLINE npy_uint16 npy_bswap2 ( npy_uint16  x) [static]
byte swapping functions
static NPY_INLINE void npy_bswap2_unaligned ( char *  x) [static]
treat as int16 and byteswap unaligned memory, some cpus don't support unaligned access
static NPY_INLINE npy_uint32 npy_bswap4 ( npy_uint32  x) [static]
static NPY_INLINE void npy_bswap4_unaligned ( char *  x) [static]
static NPY_INLINE npy_uint64 npy_bswap8 ( npy_uint64  x) [static]
static NPY_INLINE void npy_bswap8_unaligned ( char *  x) [static]
NPY_NO_EXPORT int PyArray_CastRawArrays ( npy_intp  count,
char *  src,
char *  dst,
npy_intp  src_stride,
npy_intp  dst_stride,
PyArray_Descr src_dtype,
PyArray_Descr dst_dtype,
int  move_references 
)
Casts the specified number of elements from 'src' with data type 'src_dtype' to 'dst' with 'dst_dtype'. See PyArray_GetDTypeTransferFunction for more details.
Returns NPY_SUCCEED or NPY_FAIL.
Make sure the copy is reasonable
Check data alignment
Get the function to do the casting
Cast
Cleanup
If needs_api was set to 1, it may have raised a Python exception
NPY_NO_EXPORT int PyArray_GetDTypeCopySwapFn ( int  aligned,
npy_intp  src_stride,
npy_intp  dst_stride,
PyArray_Descr dtype,
PyArray_StridedUnaryOp **  outstransfer,
NpyAuxData **  outtransferdata 
)
Gets an operation which copies elements of the given dtype, swapping if the dtype isn't in NBO.
Returns NPY_SUCCEED or NPY_FAIL
*************** DTYPE COPY SWAP FUNCTION ******************
If it's a custom data type, wrap its copy swap function
A straight copy
If it's not complex, one swap
If complex, a paired swap

Referenced by get_nbo_datetime_to_string_transfer_function().

NPY_NO_EXPORT int PyArray_GetDTypeTransferFunction ( int  aligned,
npy_intp  src_stride,
npy_intp  dst_stride,
PyArray_Descr src_dtype,
PyArray_Descr dst_dtype,
int  move_references,
PyArray_StridedUnaryOp **  out_stransfer,
NpyAuxData **  out_transferdata,
int *  out_needs_api 
)
If it's possible, gives back a transfer function which casts and/or byte swaps data with the dtype 'src_dtype' into data with the dtype 'dst_dtype'. If the outtransferdata is populated with a non-NULL value, it must be deallocated with the NPY_AUXDATA_FREE function when the transfer function is no longer required.

aligned:
Should be 1 if the src and dst pointers are always aligned, 0 otherwise.
src_stride:
Should be the src stride if it will always be the same, NPY_MAX_INTP otherwise.
dst_stride:
Should be the dst stride if it will always be the same, NPY_MAX_INTP otherwise.
src_dtype:
The data type of source data. If this is NULL, a transfer function which sets the destination to zeros is produced.
dst_dtype:
The data type of destination data. If this is NULL and move_references is 1, a transfer function which decrements source data references is produced.
move_references:
If 0, the destination data gets new reference ownership. If 1, the references from the source data are moved to the destination data.
out_stransfer:
The resulting transfer function is placed here.
out_transferdata:
The auxiliary data for the transfer function is placed here. When finished with the transfer function, the caller must call NPY_AUXDATA_FREE on this data.
out_needs_api:
If this is non-NULL, and the transfer function produced needs to call into the (Python) API, this gets set to 1. This remains untouched if no API access is required.
WARNING: If you set move_references to 1, it is best that src_stride is
never zero when calling the transfer function. Otherwise, the first destination reference will get the value and all the rest will get NULL.
Returns NPY_SUCCEED or NPY_FAIL.
*************** MAIN DTYPE TRANSFER FUNCTION ******************
If one of the dtypes is NULL, we give back either a src decref function or a dst setzero function
Common special case - number -> number NBO cast
If there are no references and the data types are equivalent, return a simple copy
We can't pass through the aligned flag because it's not appropriate. Consider a size-8 string, it will say it's aligned because strings only need alignment 1, but the copy function wants to know if it's alignment 8.

TODO: Change align from a flag to a "best power of 2 alignment"
which holds the strongest alignment value for all the data which will be used.
First look at the possibilities of just a copy or swap
A custom data type requires that we use its copy/swap
If the sizes and kinds are identical, but they're different custom types, then get a cast function
The special types, which have no or subelement byte-order
Wrap the copy swap function when swapping is necessary
This is a straight copy
This is a straight copy + byte swap
This is a straight copy + element pair byte swap
Handle subarrays
Handle fields
Check for different-sized strings, unicodes, or voids
Otherwise a cast is necessary

Referenced by _strided_to_strided_one_to_n_with_finish(), get_cast_transfer_function(), get_nbo_datetime_to_string_transfer_function(), raw_array_assign_array(), and raw_array_assign_scalar().

NPY_NO_EXPORT int PyArray_GetMaskedDTypeTransferFunction ( int  aligned,
npy_intp  src_stride,
npy_intp  dst_stride,
npy_intp  mask_stride,
PyArray_Descr src_dtype,
PyArray_Descr dst_dtype,
PyArray_Descr mask_dtype,
int  move_references,
PyArray_MaskedStridedUnaryOp **  out_stransfer,
NpyAuxData **  out_transferdata,
int *  out_needs_api 
)
This is identical to PyArray_GetDTypeTransferFunction, but returns a transfer function which also takes a mask as a parameter. The mask is used to determine which values to copy, and data is transfered exactly when mask[i*mask_stride] is true.
If move_references is true, values which are not copied to the destination will still have their source reference decremented.
If mask_dtype is NPY_BOOL or NPY_UINT8, each full element is either transferred or not according to the mask as described above. If dst_dtype and mask_dtype are both struct dtypes, their names must match exactly, and the dtype of each leaf field in mask_dtype must be either NPY_BOOL or NPY_UINT8.
TODO: Add struct-based mask_dtype support later
TODO: Special case some important cases so they're fast
Fall back to wrapping a non-masked transfer function
Create the wrapper function's auxdata
Fill in the auxdata object
If the src object will need a DECREF, get a function to handle that
NPY_NO_EXPORT PyArray_StridedUnaryOp* PyArray_GetStridedCopyFn ( int  aligned,
npy_intp  src_stride,
npy_intp  dst_stride,
npy_intp  itemsize 
)
Gives back a function pointer to a specialized function for copying strided memory. Returns NULL if there is a problem with the inputs.

aligned:
Should be 1 if the src and dst pointers are always aligned, 0 otherwise.
src_stride:
Should be the src stride if it will always be the same, NPY_MAX_INTP otherwise.
dst_stride:
Should be the dst stride if it will always be the same, NPY_MAX_INTP otherwise.
itemsize:
Should be the item size if it will always be the same, 0 otherwise.
Skip the "unaligned" versions on CPUs which support unaligned memory accesses.

<

!NPY_USE_UNALIGNED_ACCESS
contiguous dst
constant src
begin repeat
#elsize = 1, 2, 4, 8, 16#
end repeat*
contiguous src
general src
begin repeat
#elsize = 1, 2, 4, 8, 16#
end repeat*
general dst
constant src
begin repeat
#elsize = 1, 2, 4, 8, 16#
end repeat*
contiguous src
begin repeat
#elsize = 1, 2, 4, 8, 16#
end repeat*
begin repeat
#elsize = 1, 2, 4, 8, 16#
end repeat*
contiguous dst
contiguous src
general src
begin repeat
#elsize = 2, 4, 8, 16#
end repeat*
general dst
contiguous src
begin repeat
#elsize = 2, 4, 8, 16#
end repeat*
general src
begin repeat
#elsize = 2, 4, 8, 16#
end repeat*

Referenced by _strided_to_strided_truncate_copy().

NPY_NO_EXPORT PyArray_StridedUnaryOp* PyArray_GetStridedCopySwapFn ( int  aligned,
npy_intp  src_stride,
npy_intp  dst_stride,
npy_intp  itemsize 
)
Gives back a function pointer to a specialized function for copying and swapping strided memory. This assumes each element is a single value to be swapped.
For information on the 'aligned', 'src_stride' and 'dst_stride' parameters see above.
Parameters are as for PyArray_GetStridedCopyFn.
NPY_NO_EXPORT PyArray_StridedUnaryOp* PyArray_GetStridedCopySwapPairFn ( int  aligned,
npy_intp  src_stride,
npy_intp  dst_stride,
npy_intp  itemsize 
)
Gives back a function pointer to a specialized function for copying and swapping strided memory. This assumes each element is a pair of values, each of which needs to be swapped.
For information on the 'aligned', 'src_stride' and 'dst_stride' parameters see above.
Parameters are as for PyArray_GetStridedCopyFn.
NPY_NO_EXPORT PyArray_StridedUnaryOp* PyArray_GetStridedNumericCastFn ( int  aligned,
npy_intp  src_stride,
npy_intp  dst_stride,
int  src_type_num,
int  dst_type_num 
)
For casts between built-in numeric types, this produces a function pointer for casting from src_type_num to dst_type_num. If a conversion is unsupported, returns NULL without setting a Python exception.
end repeat*
******* STRIDED CASTING SPECIALIZED FUNCTIONS ********
begin repeat <blockquote>

#NAME1 = BOOL,
UBYTE, USHORT, UINT, ULONG, ULONGLONG, BYTE, SHORT, INT, LONG, LONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, CFLOAT, CDOUBLE, CLONGDOUBLE#
#name1 = bool,
ubyte, ushort, uint, ulong, ulonglong, byte, short, int, long, longlong, half, float, double, longdouble, cfloat, cdouble, clongdouble#
#type1 = npy_bool,
npy_ubyte, npy_ushort, npy_uint, npy_ulong, npy_ulonglong, npy_byte, npy_short, npy_int, npy_long, npy_longlong, npy_half, npy_float, npy_double, npy_longdouble, npy_cfloat, npy_cdouble, npy_clongdouble#
#rtype1 = npy_bool,
npy_ubyte, npy_ushort, npy_uint, npy_ulong, npy_ulonglong, npy_byte, npy_short, npy_int, npy_long, npy_longlong, npy_half, npy_float, npy_double, npy_longdouble, npy_float, npy_double, npy_longdouble#
System Message: WARNING/2 (<string>, line 23) Definition list ends without a blank line; unexpected unindent.
#is_bool1 = 1, 0*17# #is_half1 = 0*11, 1, 0*6# #is_float1 = 0*12, 1, 0, 0, 1, 0, 0# #is_double1 = 0*13, 1, 0, 0, 1, 0# #is_complex1 = 0*15, 1*3# </blockquote>
begin repeat1 <blockquote>

#NAME2 = BOOL,
UBYTE, USHORT, UINT, ULONG, ULONGLONG, BYTE, SHORT, INT, LONG, LONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, CFLOAT, CDOUBLE, CLONGDOUBLE#
#name2 = bool,
ubyte, ushort, uint, ulong, ulonglong, byte, short, int, long, longlong, half, float, double, longdouble, cfloat, cdouble, clongdouble#
#type2 = npy_bool,
npy_ubyte, npy_ushort, npy_uint, npy_ulong, npy_ulonglong, npy_byte, npy_short, npy_int, npy_long, npy_longlong, npy_half, npy_float, npy_double, npy_longdouble, npy_cfloat, npy_cdouble, npy_clongdouble#
#rtype2 = npy_bool,
npy_ubyte, npy_ushort, npy_uint, npy_ulong, npy_ulonglong, npy_byte, npy_short, npy_int, npy_long, npy_longlong, npy_half, npy_float, npy_double, npy_longdouble, npy_float, npy_double, npy_longdouble#
System Message: WARNING/2 (<string>, line 23) Definition list ends without a blank line; unexpected unindent.
#is_bool2 = 1, 0*17# #is_half2 = 0*11, 1, 0*6# #is_float2 = 0*12, 1, 0, 0, 1, 0, 0# #is_double2 = 0*13, 1, 0, 0, 1, 0# #is_complex2 = 0*15, 1*3# </blockquote>
begin repeat2
#prefix = _aligned,,_aligned_contig,_contig# #aligned = 1,0,1,0# #contig = 0,0,1,1#
end repeat2*
end repeat1*
end repeat*
begin repeat <blockquote>

#NAME1 = BOOL,
UBYTE, USHORT, UINT, ULONG, ULONGLONG, BYTE, SHORT, INT, LONG, LONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, CFLOAT, CDOUBLE, CLONGDOUBLE#
#name1 = bool,
ubyte, ushort, uint, ulong, ulonglong, byte, short, int, long, longlong, half, float, double, longdouble, cfloat, cdouble, clongdouble#
#type1 = npy_bool,
npy_ubyte, npy_ushort, npy_uint, npy_ulong, npy_ulonglong, npy_byte, npy_short, npy_int, npy_long, npy_longlong, npy_half, npy_float, npy_double, npy_longdouble, npy_cfloat, npy_cdouble, npy_clongdouble#

</blockquote>

printf("test fn d - second dn", NPY_&#64;NAME1&#64;, dst_type_num);
begin repeat1 <blockquote>

#NAME2 = BOOL,
UBYTE, USHORT, UINT, ULONG, ULONGLONG, BYTE, SHORT, INT, LONG, LONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, CFLOAT, CDOUBLE, CLONGDOUBLE#
#name2 = bool,
ubyte, ushort, uint, ulong, ulonglong, byte, short, int, long, longlong, half, float, double, longdouble, cfloat, cdouble, clongdouble#
#type2 = npy_bool,
npy_ubyte, npy_ushort, npy_uint, npy_ulong, npy_ulonglong, npy_byte, npy_short, npy_int, npy_long, npy_longlong, npy_half, npy_float, npy_double, npy_longdouble, npy_cfloat, npy_cdouble, npy_clongdouble#

</blockquote>

printf("ret fn d dn", NPY_&#64;NAME1&#64;, NPY_&#64;NAME2&#64;);
end repeat1*
printf("switched test fn d - second dn", NPY_&#64;NAME1&#64;, dst_type_num);
end repeat*
NPY_NO_EXPORT int PyArray_GetStridedZeroPadCopyFn ( int  aligned,
int  unicode_swap,
npy_intp  src_stride,
npy_intp  dst_stride,
npy_intp  src_itemsize,
npy_intp  dst_itemsize,
PyArray_StridedUnaryOp **  outstransfer,
NpyAuxData **  outtransferdata 
)
Gives back a transfer function and transfer data pair which copies the data from source to dest, truncating it if the data doesn't fit, and padding with zero bytes if there's too much space.
For information on the 'aligned', 'src_stride' and 'dst_stride' parameters see above.
Returns NPY_SUCCEED or NPY_FAIL
NPY_NO_EXPORT int PyArray_PrepareOneRawArrayIter ( int  ndim,
npy_intp shape,
char *  data,
npy_intp strides,
int *  out_ndim,
npy_intp out_shape,
char **  out_data,
npy_intp out_strides 
)
Prepares shape and strides for a simple raw array iteration. This sorts the strides into FORTRAN order, reverses any negative strides, then coalesces axes where possible. The results are filled in the output parameters.
This is intended for simple, lightweight iteration over arrays where no buffering of any kind is needed, and the array may not be stored as a PyArrayObject.
You can use this together with NPY_RAW_ITER_START and NPY_RAW_ITER_ONE_NEXT to handle the looping boilerplate of everything but the innermost loop (which is for idim == 0).
Returns 0 on success, -1 on failure.
Prepares shape and strides for a simple raw array iteration. This sorts the strides into FORTRAN order, reverses any negative strides, then coalesces axes where possible. The results are filled in the output parameters.
This is intended for simple, lightweight iteration over arrays where no buffering of any kind is needed, and the array may not be stored as a PyArrayObject.
The arrays shape, out_shape, strides, and out_strides must all point to different data.
Returns 0 on success, -1 on failure.
Special case 0 and 1 dimensions
Always make a positive stride
Sort the axes based on the destination strides
Reverse any negative strides
Detect 0-size arrays here
Coalesce any dimensions where possible
Drop axis i
Drop axis j
Coalesce axes i and j
Can't coalesce, go to next i

Referenced by raw_array_assign_scalar().

NPY_NO_EXPORT int PyArray_PrepareThreeRawArrayIter ( int  ndim,
npy_intp shape,
char *  dataA,
npy_intp stridesA,
char *  dataB,
npy_intp stridesB,
char *  dataC,
npy_intp stridesC,
int *  out_ndim,
npy_intp out_shape,
char **  out_dataA,
npy_intp out_stridesA,
char **  out_dataB,
npy_intp out_stridesB,
char **  out_dataC,
npy_intp out_stridesC 
)
The same as PyArray_PrepareOneRawArrayIter, but for three operands instead of one. Any broadcasting of the three operands should have already been done before calling this function, as the ndim and shape is only specified once for all operands.
Only the strides of the first operand are used to reorder the dimensions, no attempt to consider all the strides together is made, as is done in the NpyIter object.
You can use this together with NPY_RAW_ITER_START and NPY_RAW_ITER_THREE_NEXT to handle the looping boilerplate of everything but the innermost loop (which is for idim == 0).
Returns 0 on success, -1 on failure.
Special case 0 and 1 dimensions
Always make a positive stride for the first operand
Sort the axes based on the destination strides
Reverse any negative strides of operand A
Detect 0-size arrays here
Coalesce any dimensions where possible
Drop axis i
Drop axis j
Coalesce axes i and j
Can't coalesce, go to next i
NPY_NO_EXPORT int PyArray_PrepareTwoRawArrayIter ( int  ndim,
npy_intp shape,
char *  dataA,
npy_intp stridesA,
char *  dataB,
npy_intp stridesB,
int *  out_ndim,
npy_intp out_shape,
char **  out_dataA,
npy_intp out_stridesA,
char **  out_dataB,
npy_intp out_stridesB 
)
The same as PyArray_PrepareOneRawArrayIter, but for two operands instead of one. Any broadcasting of the two operands should have already been done before calling this function, as the ndim and shape is only specified once for both operands.
Only the strides of the first operand are used to reorder the dimensions, no attempt to consider all the strides together is made, as is done in the NpyIter object.
You can use this together with NPY_RAW_ITER_START and NPY_RAW_ITER_TWO_NEXT to handle the looping boilerplate of everything but the innermost loop (which is for idim == 0).
Returns 0 on success, -1 on failure.
Special case 0 and 1 dimensions
Always make a positive stride for the first operand
Sort the axes based on the destination strides
Reverse any negative strides of operand A
Detect 0-size arrays here
Coalesce any dimensions where possible
Drop axis i
Drop axis j
Coalesce axes i and j
Can't coalesce, go to next i

Referenced by raw_array_assign_array().

NPY_NO_EXPORT npy_intp PyArray_TransferMaskedStridedToNDim ( npy_intp  ndim,
char *  dst,
npy_intp dst_strides,
npy_intp  dst_strides_inc,
char *  src,
npy_intp  src_stride,
npy_bool mask,
npy_intp  mask_stride,
npy_intp coords,
npy_intp  coords_inc,
npy_intp shape,
npy_intp  shape_inc,
npy_intp  count,
npy_intp  src_itemsize,
PyArray_MaskedStridedUnaryOp stransfer,
NpyAuxData data 
)
NPY_NO_EXPORT npy_intp PyArray_TransferNDimToStrided ( npy_intp  ndim,
char *  dst,
npy_intp  dst_stride,
char *  src,
npy_intp src_strides,
npy_intp  src_strides_inc,
npy_intp coords,
npy_intp  coords_inc,
npy_intp shape,
npy_intp  shape_inc,
npy_intp  count,
npy_intp  src_itemsize,
PyArray_StridedUnaryOp stransfer,
NpyAuxData data 
)
These two functions copy or convert the data of an n-dimensional array to/from a 1-dimensional strided buffer. These functions will only call 'stransfer' with the provided dst_stride/src_stride and dst_strides[0]/src_strides[0], so the caller can use those values to specialize the function. Note that even if ndim == 0, everything needs to be set as if ndim == 1.
The return value is the number of elements it couldn't copy. A return value of 0 means all elements were copied, a larger value means the end of the n-dimensional array was reached before 'count' elements were copied.

ndim:
The number of dimensions of the n-dimensional array.
dst/src/mask:
The destination, source or mask starting pointer.
dst_stride/src_stride/mask_stride:
The stride of the 1-dimensional strided buffer
dst_strides/src_strides:
The strides of the n-dimensional array.
dst_strides_inc/src_strides_inc:
How much to add to the ..._strides pointer to get to the next stride.
coords:
The starting coordinates in the n-dimensional array.
coords_inc:
How much to add to the coords pointer to get to the next coordinate.
shape:
The shape of the n-dimensional array.
shape_inc:
How much to add to the shape pointer to get to the next shape entry.
count:
How many elements to transfer
src_itemsize:
How big each element is. If transfering between elements of different sizes, for example a casting operation, the 'stransfer' function should be specialized for that, in which case 'stransfer' will use this parameter as the source item size.
stransfer:
The strided transfer function.
transferdata:
An auxiliary data pointer passed to the strided transfer function. This follows the conventions of NpyAuxData objects.
************ PRIMITIVE FLAT TO/FROM NDIM FUNCTIONS *************
See documentation of arguments in lowlevel_strided_loops.h
Finish off dimension 0
If it's 1-dimensional, there's no more to copy
Adjust the src and dst pointers
Finish off dimension 1
If it's 2-dimensional, there's no more to copy
General-case loop for everything else
Iteration structure for dimensions 2 and up
Copy the coordinates and shape
Adjust the src pointer from the dimension 0 and 1 loop
Increment to the next coordinate
If the last dimension rolled over, we're done
A loop for dimensions 0 and 1
NPY_NO_EXPORT npy_intp PyArray_TransferStridedToNDim ( npy_intp  ndim,
char *  dst,
npy_intp dst_strides,
npy_intp  dst_strides_inc,
char *  src,
npy_intp  src_stride,
npy_intp coords,
npy_intp  coords_inc,
npy_intp shape,
npy_intp  shape_inc,
npy_intp  count,
npy_intp  src_itemsize,
PyArray_StridedUnaryOp stransfer,
NpyAuxData data 
)
See documentation of arguments in lowlevel_strided_loops.h
Finish off dimension 0
If it's 1-dimensional, there's no more to copy
Adjust the src and dst pointers
Finish off dimension 1
If it's 2-dimensional, there's no more to copy
General-case loop for everything else
Iteration structure for dimensions 2 and up
Copy the coordinates and shape
Adjust the dst pointer from the dimension 0 and 1 loop
Increment to the next coordinate
If the last dimension rolled over, we're done
A loop for dimensions 0 and 1

Referenced by npyiter_allocate_buffers().