summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--numpy/core/src/multiarray/nditer_api.c314
-rw-r--r--numpy/core/src/multiarray/nditer_constr.c44
-rw-r--r--numpy/core/src/multiarray/nditer_impl.h26
3 files changed, 204 insertions, 180 deletions
diff --git a/numpy/core/src/multiarray/nditer_api.c b/numpy/core/src/multiarray/nditer_api.c
index a433df406..cceec518b 100644
--- a/numpy/core/src/multiarray/nditer_api.c
+++ b/numpy/core/src/multiarray/nditer_api.c
@@ -771,7 +771,7 @@ NpyIter_RequiresBuffering(NpyIter *iter)
/*int ndim = NIT_NDIM(iter);*/
int iop, nop = NIT_NOP(iter);
- char *op_itflags;
+ npyiter_opitflags *op_itflags;
if (!(itflags&NPY_ITFLAG_BUFFER)) {
return 0;
@@ -1217,7 +1217,7 @@ NpyIter_GetReadFlags(NpyIter *iter, char *outreadflags)
/*int ndim = NIT_NDIM(iter);*/
int iop, nop = NIT_NOP(iter);
- char *op_itflags = NIT_OPITFLAGS(iter);
+ npyiter_opitflags *op_itflags = NIT_OPITFLAGS(iter);
for (iop = 0; iop < nop; ++iop) {
outreadflags[iop] = (op_itflags[iop]&NPY_OP_ITFLAG_READ) != 0;
@@ -1234,7 +1234,7 @@ NpyIter_GetWriteFlags(NpyIter *iter, char *outwriteflags)
/*int ndim = NIT_NDIM(iter);*/
int iop, nop = NIT_NOP(iter);
- char *op_itflags = NIT_OPITFLAGS(iter);
+ npyiter_opitflags *op_itflags = NIT_OPITFLAGS(iter);
for (iop = 0; iop < nop; ++iop) {
outwriteflags[iop] = (op_itflags[iop]&NPY_OP_ITFLAG_WRITE) != 0;
@@ -1330,7 +1330,7 @@ NpyIter_GetInnerFixedStrideArray(NpyIter *iter, npy_intp *out_strides)
if (itflags&NPY_ITFLAG_BUFFER) {
NpyIter_BufferData *data = NIT_BUFFERDATA(iter);
- char *op_itflags = NIT_OPITFLAGS(iter);
+ npyiter_opitflags *op_itflags = NIT_OPITFLAGS(iter);
npy_intp stride, *strides = NBF_STRIDES(data),
*ad_strides = NAD_STRIDES(axisdata0);
PyArray_Descr **dtypes = NIT_DTYPES(iter);
@@ -1751,14 +1751,14 @@ npyiter_allocate_buffers(NpyIter *iter, char **errmsg)
int iop = 0, nop = NIT_NOP(iter);
npy_intp i;
- char *op_itflags = NIT_OPITFLAGS(iter);
+ npyiter_opitflags *op_itflags = NIT_OPITFLAGS(iter);
NpyIter_BufferData *bufferdata = NIT_BUFFERDATA(iter);
PyArray_Descr **op_dtype = NIT_DTYPES(iter);
npy_intp buffersize = NBF_BUFFERSIZE(bufferdata);
char *buffer, **buffers = NBF_BUFFERS(bufferdata);
for (iop = 0; iop < nop; ++iop) {
- char flags = op_itflags[iop];
+ npyiter_opitflags flags = op_itflags[iop];
/*
* If we have determined that a buffer may be needed,
@@ -1889,7 +1889,7 @@ npyiter_copy_from_buffers(NpyIter *iter)
int maskop = NIT_MASKOP(iter);
int first_maskna_op = NIT_FIRST_MASKNA_OP(iter);
- char *op_itflags = NIT_OPITFLAGS(iter);
+ npyiter_opitflags *op_itflags = NIT_OPITFLAGS(iter);
NpyIter_BufferData *bufferdata = NIT_BUFFERDATA(iter);
NpyIter_AxisData *axisdata = NIT_AXISDATA(iter),
*reduce_outeraxisdata = NULL;
@@ -1935,168 +1935,165 @@ npyiter_copy_from_buffers(NpyIter *iter)
/*
* Copy the data back to the arrays. If the type has refs,
* this function moves them so the buffer's refs are released.
+ *
+ * The flag USINGBUFFER is set when the buffer was used, so
+ * only copy back when this flag is on.
*/
- if ((stransfer != NULL) && (op_itflags[iop]&NPY_OP_ITFLAG_WRITE)) {
- /* Copy back only if the pointer was pointing to the buffer */
- npy_intp delta = (ptrs[iop] - buffer);
- if (0 <= delta && delta <= buffersize*dtypes[iop]->elsize) {
- npy_intp op_transfersize;
+ if ((stransfer != NULL) &&
+ (op_itflags[iop]&(NPY_OP_ITFLAG_WRITE|NPY_OP_ITFLAG_USINGBUFFER))
+ == (NPY_OP_ITFLAG_WRITE|NPY_OP_ITFLAG_USINGBUFFER)) {
+ npy_intp op_transfersize;
- npy_intp src_stride, *dst_strides, *dst_coords, *dst_shape;
- int ndim_transfer;
+ npy_intp src_stride, *dst_strides, *dst_coords, *dst_shape;
+ int ndim_transfer;
- NPY_IT_DBG_PRINT1("Iterator: Operand %d was buffered\n",
- (int)iop);
+ NPY_IT_DBG_PRINT1("Iterator: Operand %d was buffered\n",
+ (int)iop);
- /*
- * If this operand is being reduced in the inner loop,
- * its buffering stride was set to zero, and just
- * one element was copied.
- */
- if (op_itflags[iop]&NPY_OP_ITFLAG_REDUCE) {
- if (strides[iop] == 0) {
- if (reduce_outerstrides[iop] == 0) {
- op_transfersize = 1;
- src_stride = 0;
- dst_strides = &src_stride;
- dst_coords = &NAD_INDEX(reduce_outeraxisdata);
- dst_shape = &NAD_SHAPE(reduce_outeraxisdata);
- ndim_transfer = 1;
- }
- else {
- op_transfersize = NBF_REDUCE_OUTERSIZE(bufferdata);
- src_stride = reduce_outerstrides[iop];
- dst_strides =
- &NAD_STRIDES(reduce_outeraxisdata)[iop];
- dst_coords = &NAD_INDEX(reduce_outeraxisdata);
- dst_shape = &NAD_SHAPE(reduce_outeraxisdata);
- ndim_transfer = ndim - reduce_outerdim;
- }
+ /*
+ * If this operand is being reduced in the inner loop,
+ * its buffering stride was set to zero, and just
+ * one element was copied.
+ */
+ if (op_itflags[iop]&NPY_OP_ITFLAG_REDUCE) {
+ if (strides[iop] == 0) {
+ if (reduce_outerstrides[iop] == 0) {
+ op_transfersize = 1;
+ src_stride = 0;
+ dst_strides = &src_stride;
+ dst_coords = &NAD_INDEX(reduce_outeraxisdata);
+ dst_shape = &NAD_SHAPE(reduce_outeraxisdata);
+ ndim_transfer = 1;
}
else {
- if (reduce_outerstrides[iop] == 0) {
- op_transfersize = NBF_SIZE(bufferdata);
- src_stride = strides[iop];
- dst_strides = &ad_strides[iop];
- dst_coords = &NAD_INDEX(axisdata);
- dst_shape = &NAD_SHAPE(axisdata);
- ndim_transfer = reduce_outerdim ?
- reduce_outerdim : 1;
- }
- else {
- op_transfersize = transfersize;
- src_stride = strides[iop];
- dst_strides = &ad_strides[iop];
- dst_coords = &NAD_INDEX(axisdata);
- dst_shape = &NAD_SHAPE(axisdata);
- ndim_transfer = ndim;
- }
+ op_transfersize = NBF_REDUCE_OUTERSIZE(bufferdata);
+ src_stride = reduce_outerstrides[iop];
+ dst_strides =
+ &NAD_STRIDES(reduce_outeraxisdata)[iop];
+ dst_coords = &NAD_INDEX(reduce_outeraxisdata);
+ dst_shape = &NAD_SHAPE(reduce_outeraxisdata);
+ ndim_transfer = ndim - reduce_outerdim;
}
}
else {
- op_transfersize = transfersize;
- src_stride = strides[iop];
- dst_strides = &ad_strides[iop];
- dst_coords = &NAD_INDEX(axisdata);
- dst_shape = &NAD_SHAPE(axisdata);
- ndim_transfer = ndim;
- }
-
- NPY_IT_DBG_PRINT2("Iterator: Copying buffer to "
- "operand %d (%d items)\n",
- (int)iop, (int)op_transfersize);
-
- /* USE_MASKNA operand */
- if (iop < first_maskna_op && maskna_indices[iop] >= 0) {
- int iop_maskna = maskna_indices[iop];
- npy_mask *maskptr;
- /* TODO: support WRITEMASKED + USE_MASKNA together */
-
- /*
- * The mask pointer may be in the buffer or in
- * the array, detect which one.
- */
- delta = (ptrs[iop_maskna] - buffers[iop_maskna]);
- if (0 <= delta &&
- delta <= buffersize*dtypes[iop_maskna]->elsize) {
- maskptr = (npy_mask *)buffers[iop_maskna];
+ if (reduce_outerstrides[iop] == 0) {
+ op_transfersize = NBF_SIZE(bufferdata);
+ src_stride = strides[iop];
+ dst_strides = &ad_strides[iop];
+ dst_coords = &NAD_INDEX(axisdata);
+ dst_shape = &NAD_SHAPE(axisdata);
+ ndim_transfer = reduce_outerdim ?
+ reduce_outerdim : 1;
}
else {
- maskptr = (npy_mask *)ad_ptrs[iop_maskna];
+ op_transfersize = transfersize;
+ src_stride = strides[iop];
+ dst_strides = &ad_strides[iop];
+ dst_coords = &NAD_INDEX(axisdata);
+ dst_shape = &NAD_SHAPE(axisdata);
+ ndim_transfer = ndim;
}
+ }
+ }
+ else {
+ op_transfersize = transfersize;
+ src_stride = strides[iop];
+ dst_strides = &ad_strides[iop];
+ dst_coords = &NAD_INDEX(axisdata);
+ dst_shape = &NAD_SHAPE(axisdata);
+ ndim_transfer = ndim;
+ }
+
+ NPY_IT_DBG_PRINT2("Iterator: Copying buffer to "
+ "operand %d (%d items)\n",
+ (int)iop, (int)op_transfersize);
- PyArray_TransferMaskedStridedToNDim(ndim_transfer,
- ad_ptrs[iop], dst_strides, axisdata_incr,
- buffer, src_stride,
- maskptr, strides[iop_maskna],
- dst_coords, axisdata_incr,
- dst_shape, axisdata_incr,
- op_transfersize, dtypes[iop]->elsize,
- (PyArray_MaskedStridedUnaryOp *)stransfer,
- transferdata);
+ /* USE_MASKNA operand */
+ if (iop < first_maskna_op && maskna_indices[iop] >= 0) {
+ int iop_maskna = maskna_indices[iop];
+ npy_mask *maskptr;
+ /* TODO: support WRITEMASKED + USE_MASKNA together */
+
+ /*
+ * The mask pointer may be in the buffer or in
+ * the array, detect which one.
+ */
+ if ((op_itflags[iop_maskna]&NPY_OP_ITFLAG_USINGBUFFER) != 0) {
+ maskptr = (npy_mask *)buffers[iop_maskna];
}
- /* WRITEMASKED operand */
- else if (op_itflags[iop] & NPY_OP_ITFLAG_WRITEMASKED) {
- npy_mask *maskptr;
-
- /*
- * The mask pointer may be in the buffer or in
- * the array, detect which one.
- */
- delta = (ptrs[maskop] - buffers[maskop]);
- if (0 <= delta &&
- delta <= buffersize*dtypes[maskop]->elsize) {
- maskptr = (npy_mask *)buffers[maskop];
- }
- else {
- maskptr = (npy_mask *)ad_ptrs[maskop];
- }
+ else {
+ maskptr = (npy_mask *)ad_ptrs[iop_maskna];
+ }
+
+ PyArray_TransferMaskedStridedToNDim(ndim_transfer,
+ ad_ptrs[iop], dst_strides, axisdata_incr,
+ buffer, src_stride,
+ maskptr, strides[iop_maskna],
+ dst_coords, axisdata_incr,
+ dst_shape, axisdata_incr,
+ op_transfersize, dtypes[iop]->elsize,
+ (PyArray_MaskedStridedUnaryOp *)stransfer,
+ transferdata);
+ }
+ /* WRITEMASKED operand */
+ else if (op_itflags[iop] & NPY_OP_ITFLAG_WRITEMASKED) {
+ npy_mask *maskptr;
- PyArray_TransferMaskedStridedToNDim(ndim_transfer,
- ad_ptrs[iop], dst_strides, axisdata_incr,
- buffer, src_stride,
- maskptr, strides[maskop],
- dst_coords, axisdata_incr,
- dst_shape, axisdata_incr,
- op_transfersize, dtypes[iop]->elsize,
- (PyArray_MaskedStridedUnaryOp *)stransfer,
- transferdata);
+ /*
+ * The mask pointer may be in the buffer or in
+ * the array, detect which one.
+ */
+ if ((op_itflags[maskop]&NPY_OP_ITFLAG_USINGBUFFER) != 0) {
+ maskptr = (npy_mask *)buffers[maskop];
}
- /* Regular operand */
else {
- PyArray_TransferStridedToNDim(ndim_transfer,
- ad_ptrs[iop], dst_strides, axisdata_incr,
- buffer, src_stride,
- dst_coords, axisdata_incr,
- dst_shape, axisdata_incr,
- op_transfersize, dtypes[iop]->elsize,
- stransfer,
- transferdata);
+ maskptr = (npy_mask *)ad_ptrs[maskop];
}
+
+ PyArray_TransferMaskedStridedToNDim(ndim_transfer,
+ ad_ptrs[iop], dst_strides, axisdata_incr,
+ buffer, src_stride,
+ maskptr, strides[maskop],
+ dst_coords, axisdata_incr,
+ dst_shape, axisdata_incr,
+ op_transfersize, dtypes[iop]->elsize,
+ (PyArray_MaskedStridedUnaryOp *)stransfer,
+ transferdata);
+ }
+ /* Regular operand */
+ else {
+ PyArray_TransferStridedToNDim(ndim_transfer,
+ ad_ptrs[iop], dst_strides, axisdata_incr,
+ buffer, src_stride,
+ dst_coords, axisdata_incr,
+ dst_shape, axisdata_incr,
+ op_transfersize, dtypes[iop]->elsize,
+ stransfer,
+ transferdata);
}
}
/* 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.
+ *
+ * The flag USINGBUFFER is set when the buffer was used, so
+ * only decrement refs when this flag is on.
*/
- else if (stransfer != NULL) {
- /* Decrement refs only if the pointer was pointing to the buffer */
- npy_intp delta = (ptrs[iop] - buffer);
- if (0 <= delta && delta <= transfersize*dtypes[iop]->elsize) {
- NPY_IT_DBG_PRINT1("Iterator: Freeing refs and zeroing buffer "
- "of operand %d\n", (int)iop);
- /* Decrement refs */
- stransfer(NULL, 0, buffer, dtypes[iop]->elsize,
- transfersize, dtypes[iop]->elsize,
- transferdata);
- /*
- * 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.
- */
- memset(buffer, 0, dtypes[iop]->elsize*transfersize);
- }
+ else if (stransfer != NULL &&
+ (op_itflags[iop]&NPY_OP_ITFLAG_USINGBUFFER) != 0) {
+ NPY_IT_DBG_PRINT1("Iterator: Freeing refs and zeroing buffer "
+ "of operand %d\n", (int)iop);
+ /* Decrement refs */
+ stransfer(NULL, 0, buffer, dtypes[iop]->elsize,
+ transfersize, dtypes[iop]->elsize,
+ transferdata);
+ /*
+ * 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.
+ */
+ memset(buffer, 0, dtypes[iop]->elsize*transfersize);
}
}
@@ -2116,7 +2113,7 @@ npyiter_copy_to_buffers(NpyIter *iter, char **prev_dataptrs)
int iop, nop = NIT_NOP(iter);
int first_maskna_op = NIT_FIRST_MASKNA_OP(iter);
- char *op_itflags = NIT_OPITFLAGS(iter);
+ npyiter_opitflags *op_itflags = NIT_OPITFLAGS(iter);
NpyIter_BufferData *bufferdata = NIT_BUFFERDATA(iter);
NpyIter_AxisData *axisdata = NIT_AXISDATA(iter),
*reduce_outeraxisdata = NULL;
@@ -2265,6 +2262,7 @@ npyiter_copy_to_buffers(NpyIter *iter, char **prev_dataptrs)
* to the first non-trivial stride.
*/
stransfer = NULL;
+ /* The flag NPY_OP_ITFLAG_USINGBUFFER can be ignored here */
break;
/* Never need to buffer this operand */
case NPY_OP_ITFLAG_BUFNEVER|NPY_OP_ITFLAG_REDUCE:
@@ -2277,6 +2275,7 @@ npyiter_copy_to_buffers(NpyIter *iter, char **prev_dataptrs)
* to the first non-trivial stride.
*/
stransfer = NULL;
+ /* The flag NPY_OP_ITFLAG_USINGBUFFER can be ignored here */
break;
/* Just a copy */
case 0:
@@ -2290,6 +2289,8 @@ npyiter_copy_to_buffers(NpyIter *iter, char **prev_dataptrs)
ptrs[iop] = ad_ptrs[iop];
strides[iop] = ad_strides[iop];
stransfer = NULL;
+ /* Signal that the buffer is not being used */
+ op_itflags[iop] &= (~NPY_OP_ITFLAG_USINGBUFFER);
}
/* If some other op is reduced, we have a double reduce loop */
else if ((itflags&NPY_ITFLAG_REDUCE) &&
@@ -2303,6 +2304,8 @@ npyiter_copy_to_buffers(NpyIter *iter, char **prev_dataptrs)
reduce_outerstrides[iop] =
NAD_STRIDES(reduce_outeraxisdata)[iop];
stransfer = NULL;
+ /* Signal that the buffer is not being used */
+ op_itflags[iop] &= (~NPY_OP_ITFLAG_USINGBUFFER);
}
else {
/* In this case, the buffer is being used */
@@ -2313,6 +2316,8 @@ npyiter_copy_to_buffers(NpyIter *iter, char **prev_dataptrs)
strides[iop];
reduce_outerptrs[iop] = ptrs[iop];
}
+ /* Signal that the buffer is being used */
+ op_itflags[iop] |= NPY_OP_ITFLAG_USINGBUFFER;
}
break;
/* Just a copy, but with a reduction */
@@ -2325,6 +2330,8 @@ npyiter_copy_to_buffers(NpyIter *iter, char **prev_dataptrs)
ptrs[iop] = ad_ptrs[iop];
reduce_outerstrides[iop] = 0;
stransfer = NULL;
+ /* Signal that the buffer is not being used */
+ op_itflags[iop] &= (~NPY_OP_ITFLAG_USINGBUFFER);
}
/* It's all in one stride in the reduce outer loop */
else if ((reduce_outerdim > 0) &&
@@ -2338,6 +2345,8 @@ npyiter_copy_to_buffers(NpyIter *iter, char **prev_dataptrs)
reduce_outerstrides[iop] =
NAD_STRIDES(reduce_outeraxisdata)[iop];
stransfer = NULL;
+ /* Signal that the buffer is not being used */
+ op_itflags[iop] &= (~NPY_OP_ITFLAG_USINGBUFFER);
}
/* In this case, the buffer is being used */
else {
@@ -2351,6 +2360,8 @@ npyiter_copy_to_buffers(NpyIter *iter, char **prev_dataptrs)
else {
reduce_outerstrides[iop] = dtypes[iop]->elsize;
}
+ /* Signal that the buffer is being used */
+ op_itflags[iop] |= NPY_OP_ITFLAG_USINGBUFFER;
}
}
@@ -2360,6 +2371,8 @@ npyiter_copy_to_buffers(NpyIter *iter, char **prev_dataptrs)
strides[iop] = ad_strides[iop];
reduce_outerstrides[iop] = 0;
stransfer = NULL;
+ /* Signal that the buffer is not being used */
+ op_itflags[iop] &= (~NPY_OP_ITFLAG_USINGBUFFER);
}
else {
/* It's all in one stride in the reduce outer loop */
@@ -2373,6 +2386,8 @@ npyiter_copy_to_buffers(NpyIter *iter, char **prev_dataptrs)
reduce_outerstrides[iop] =
NAD_STRIDES(reduce_outeraxisdata)[iop];
stransfer = NULL;
+ /* Signal that the buffer is not being used */
+ op_itflags[iop] &= (~NPY_OP_ITFLAG_USINGBUFFER);
}
/* In this case, the buffer is being used */
else {
@@ -2388,6 +2403,8 @@ npyiter_copy_to_buffers(NpyIter *iter, char **prev_dataptrs)
reduce_outerstrides[iop] = reduce_innersize *
dtypes[iop]->elsize;
}
+ /* Signal that the buffer is being used */
+ op_itflags[iop] |= NPY_OP_ITFLAG_USINGBUFFER;
}
}
reduce_outerptrs[iop] = ptrs[iop];
@@ -2396,6 +2413,9 @@ npyiter_copy_to_buffers(NpyIter *iter, char **prev_dataptrs)
/* In this case, the buffer is always being used */
any_buffered = 1;
+ /* Signal that the buffer is being used */
+ op_itflags[iop] |= NPY_OP_ITFLAG_USINGBUFFER;
+
if (!(op_itflags[iop]&NPY_OP_ITFLAG_REDUCE)) {
ptrs[iop] = buffers[iop];
strides[iop] = dtypes[iop]->elsize;
@@ -2636,7 +2656,7 @@ npyiter_checkreducesize(NpyIter *iter, npy_intp count,
npy_intp reducespace = 1, factor;
npy_bool nonzerocoord;
- char *op_itflags = NIT_OPITFLAGS(iter);
+ npyiter_opitflags *op_itflags = NIT_OPITFLAGS(iter);
char stride0op[NPY_MAXARGS];
/* Default to no outer axis */
diff --git a/numpy/core/src/multiarray/nditer_constr.c b/numpy/core/src/multiarray/nditer_constr.c
index 941ce91c0..f1d0c5c38 100644
--- a/numpy/core/src/multiarray/nditer_constr.c
+++ b/numpy/core/src/multiarray/nditer_constr.c
@@ -27,14 +27,14 @@ static int
npyiter_calculate_ndim(int nop, PyArrayObject **op_in,
int oa_ndim);
static int
-npyiter_check_per_op_flags(npy_uint32 flags, char *op_itflags);
+npyiter_check_per_op_flags(npy_uint32 flags, npyiter_opitflags *op_itflags);
static int
npyiter_prepare_one_operand(PyArrayObject **op,
char **op_dataptr,
PyArray_Descr *op_request_dtype,
PyArray_Descr** op_dtype,
npy_uint32 flags,
- npy_uint32 op_flags, char *op_itflags);
+ npy_uint32 op_flags, npyiter_opitflags *op_itflags);
static int
npyiter_prepare_operands(int nop, int first_maskna_op,
PyArrayObject **op_in,
@@ -43,16 +43,16 @@ npyiter_prepare_operands(int nop, int first_maskna_op,
PyArray_Descr **op_request_dtypes,
PyArray_Descr **op_dtype,
npy_uint32 flags,
- npy_uint32 *op_flags, char *op_itflags,
+ npy_uint32 *op_flags, npyiter_opitflags *op_itflags,
npy_int8 *out_maskop,
npy_int8 *out_maskna_indices);
static int
npyiter_check_casting(int nop, PyArrayObject **op,
PyArray_Descr **op_dtype,
NPY_CASTING casting,
- char *op_itflags);
+ npyiter_opitflags *op_itflags);
static int
-npyiter_fill_axisdata(NpyIter *iter, npy_uint32 flags, char *op_itflags,
+npyiter_fill_axisdata(NpyIter *iter, npy_uint32 flags, npyiter_opitflags *op_itflags,
char **op_dataptr,
npy_uint32 *op_flags, int **op_axes,
npy_intp *itershape,
@@ -74,25 +74,25 @@ static void
npyiter_find_best_axis_ordering(NpyIter *iter);
static PyArray_Descr *
npyiter_get_common_dtype(int first_maskna_op, PyArrayObject **op,
- char *op_itflags, PyArray_Descr **op_dtype,
+ npyiter_opitflags *op_itflags, PyArray_Descr **op_dtype,
PyArray_Descr **op_request_dtypes,
int only_inputs, int output_scalars);
static PyArrayObject *
npyiter_new_temp_array(NpyIter *iter, PyTypeObject *subtype,
- npy_uint32 flags, char *op_itflags,
+ npy_uint32 flags, npyiter_opitflags *op_itflags,
int op_ndim, npy_intp *shape,
PyArray_Descr *op_dtype, int *op_axes);
static int
npyiter_allocate_arrays(NpyIter *iter,
npy_uint32 flags,
PyArray_Descr **op_dtype, PyTypeObject *subtype,
- npy_uint32 *op_flags, char *op_itflags,
+ npy_uint32 *op_flags, npyiter_opitflags *op_itflags,
int **op_axes, int output_scalars);
static int
npyiter_fill_maskna_axisdata(NpyIter *iter, int **op_axes);
static void
npyiter_get_priority_subtype(int first_maskna_op, PyArrayObject **op,
- char *op_itflags,
+ npyiter_opitflags *op_itflags,
double *subtype_priority, PyTypeObject **subtype);
static int
npyiter_allocate_transfer_functions(NpyIter *iter);
@@ -120,7 +120,7 @@ NpyIter_AdvancedNew(int nop, PyArrayObject **op_in, npy_uint32 flags,
/* Per-operand values */
PyArrayObject **op;
PyArray_Descr **op_dtype;
- char *op_itflags;
+ npyiter_opitflags *op_itflags;
char **op_dataptr;
npy_int8 *perm;
@@ -916,7 +916,7 @@ npyiter_calculate_ndim(int nop, PyArrayObject **op_in,
* Returns 1 on success, 0 on failure.
*/
static int
-npyiter_check_per_op_flags(npy_uint32 op_flags, char *op_itflags)
+npyiter_check_per_op_flags(npy_uint32 op_flags, npyiter_opitflags *op_itflags)
{
if ((op_flags & NPY_ITER_GLOBAL_FLAGS) != 0) {
PyErr_SetString(PyExc_ValueError,
@@ -1027,7 +1027,7 @@ npyiter_prepare_one_operand(PyArrayObject **op,
PyArray_Descr *op_request_dtype,
PyArray_Descr **op_dtype,
npy_uint32 flags,
- npy_uint32 op_flags, char *op_itflags)
+ npy_uint32 op_flags, npyiter_opitflags *op_itflags)
{
/* NULL operands must be automatically allocated outputs */
if (*op == NULL) {
@@ -1228,7 +1228,7 @@ npyiter_prepare_operands(int nop, int first_maskna_op, PyArrayObject **op_in,
PyArray_Descr **op_request_dtypes,
PyArray_Descr **op_dtype,
npy_uint32 flags,
- npy_uint32 *op_flags, char *op_itflags,
+ npy_uint32 *op_flags, npyiter_opitflags *op_itflags,
npy_int8 *out_maskop,
npy_int8 *out_maskna_indices)
{
@@ -1421,7 +1421,7 @@ static int
npyiter_check_casting(int first_maskna_op, PyArrayObject **op,
PyArray_Descr **op_dtype,
NPY_CASTING casting,
- char *op_itflags)
+ npyiter_opitflags *op_itflags)
{
int iop;
@@ -1559,7 +1559,7 @@ check_mask_for_writemasked_reduction(NpyIter *iter, int iop)
* Returns 1 on success, 0 on failure.
*/
static int
-npyiter_fill_axisdata(NpyIter *iter, npy_uint32 flags, char *op_itflags,
+npyiter_fill_axisdata(NpyIter *iter, npy_uint32 flags, npyiter_opitflags *op_itflags,
char **op_dataptr,
npy_uint32 *op_flags, int **op_axes,
npy_intp *itershape,
@@ -2522,7 +2522,7 @@ npyiter_find_best_axis_ordering(NpyIter *iter)
*/
static PyArray_Descr *
npyiter_get_common_dtype(int first_maskna_op, PyArrayObject **op,
- char *op_itflags, PyArray_Descr **op_dtype,
+ npyiter_opitflags *op_itflags, PyArray_Descr **op_dtype,
PyArray_Descr **op_request_dtypes,
int only_inputs, int output_scalars)
{
@@ -2588,7 +2588,7 @@ npyiter_get_common_dtype(int first_maskna_op, PyArrayObject **op,
*/
static PyArrayObject *
npyiter_new_temp_array(NpyIter *iter, PyTypeObject *subtype,
- npy_uint32 flags, char *op_itflags,
+ npy_uint32 flags, npyiter_opitflags *op_itflags,
int op_ndim, npy_intp *shape,
PyArray_Descr *op_dtype, int *op_axes)
{
@@ -2822,7 +2822,7 @@ static int
npyiter_allocate_arrays(NpyIter *iter,
npy_uint32 flags,
PyArray_Descr **op_dtype, PyTypeObject *subtype,
- npy_uint32 *op_flags, char *op_itflags,
+ npy_uint32 *op_flags, npyiter_opitflags *op_itflags,
int **op_axes, int output_scalars)
{
npy_uint32 itflags = NIT_ITFLAGS(iter);
@@ -3157,7 +3157,7 @@ npyiter_fill_maskna_axisdata(NpyIter *iter, int **op_axes)
int first_maskna_op = NIT_FIRST_MASKNA_OP(iter);
npy_int8 *perm;
- char *op_itflags = NIT_OPITFLAGS(iter);
+ npyiter_opitflags *op_itflags = NIT_OPITFLAGS(iter);
npy_int8 *maskna_indices = NIT_MASKNA_INDICES(iter);
NpyIter_AxisData *axisdata;
npy_intp sizeof_axisdata;
@@ -3291,7 +3291,7 @@ npyiter_fill_maskna_axisdata(NpyIter *iter, int **op_axes)
*/
static void
npyiter_get_priority_subtype(int first_maskna_op, PyArrayObject **op,
- char *op_itflags,
+ npyiter_opitflags *op_itflags,
double *subtype_priority,
PyTypeObject **subtype)
{
@@ -3317,7 +3317,7 @@ npyiter_allocate_transfer_functions(NpyIter *iter)
int first_maskna_op = NIT_FIRST_MASKNA_OP(iter);
npy_intp i;
- char *op_itflags = NIT_OPITFLAGS(iter);
+ npyiter_opitflags *op_itflags = NIT_OPITFLAGS(iter);
NpyIter_BufferData *bufferdata = NIT_BUFFERDATA(iter);
NpyIter_AxisData *axisdata = NIT_AXISDATA(iter);
PyArrayObject **op = NIT_OPERANDS(iter);
@@ -3334,7 +3334,7 @@ npyiter_allocate_transfer_functions(NpyIter *iter)
int needs_api = 0;
for (iop = 0; iop < nop; ++iop) {
- char flags = op_itflags[iop];
+ npyiter_opitflags flags = op_itflags[iop];
/*
* Reduction operands may be buffered with a different stride,
* so we must pass NPY_MAX_INTP to the transfer function factory.
diff --git a/numpy/core/src/multiarray/nditer_impl.h b/numpy/core/src/multiarray/nditer_impl.h
index ea02d5cc4..ef10308fb 100644
--- a/numpy/core/src/multiarray/nditer_impl.h
+++ b/numpy/core/src/multiarray/nditer_impl.h
@@ -107,21 +107,23 @@
/* Internal iterator per-operand iterator flags */
/* The operand will be written to */
-#define NPY_OP_ITFLAG_WRITE 0x01
+#define NPY_OP_ITFLAG_WRITE 0x0001
/* The operand will be read from */
-#define NPY_OP_ITFLAG_READ 0x02
+#define NPY_OP_ITFLAG_READ 0x0002
/* The operand needs type conversion/byte swapping/alignment */
-#define NPY_OP_ITFLAG_CAST 0x04
+#define NPY_OP_ITFLAG_CAST 0x0004
/* The operand never needs buffering */
-#define NPY_OP_ITFLAG_BUFNEVER 0x08
+#define NPY_OP_ITFLAG_BUFNEVER 0x0008
/* The operand is aligned */
-#define NPY_OP_ITFLAG_ALIGNED 0x10
+#define NPY_OP_ITFLAG_ALIGNED 0x0010
/* The operand is being reduced */
-#define NPY_OP_ITFLAG_REDUCE 0x20
+#define NPY_OP_ITFLAG_REDUCE 0x0020
/* The operand is for temporary use, does not have a backing array */
-#define NPY_OP_ITFLAG_VIRTUAL 0x40
+#define NPY_OP_ITFLAG_VIRTUAL 0x0040
/* The operand requires masking when copying buffer -> array */
-#define NPY_OP_ITFLAG_WRITEMASKED 0x80
+#define NPY_OP_ITFLAG_WRITEMASKED 0x0080
+/* The operand's data pointer is pointing into its buffer */
+#define NPY_OP_ITFLAG_USINGBUFFER 0x0100
/*
* The data layout of the iterator is fully specified by
@@ -147,6 +149,8 @@ struct NpyIter_InternalOnly {
typedef struct NpyIter_AD NpyIter_AxisData;
typedef struct NpyIter_BD NpyIter_BufferData;
+typedef npy_int16 npyiter_opitflags;
+
/* Byte sizes of the iterator members */
#define NIT_PERM_SIZEOF(itflags, ndim, nop) \
NPY_INTP_ALIGNED(NPY_MAXDIMS)
@@ -161,7 +165,7 @@ typedef struct NpyIter_BD NpyIter_BufferData;
#define NIT_OPERANDS_SIZEOF(itflags, ndim, nop) \
((NPY_SIZEOF_INTP)*(nop))
#define NIT_OPITFLAGS_SIZEOF(itflags, ndim, nop) \
- (NPY_INTP_ALIGNED(nop))
+ (NPY_INTP_ALIGNED(sizeof(npyiter_opitflags) * nop))
#define NIT_BUFFERDATA_SIZEOF(itflags, ndim, nop) \
((itflags&NPY_ITFLAG_BUFFER) ? ((NPY_SIZEOF_INTP)*(6 + 9*nop)) : 0)
@@ -224,8 +228,8 @@ typedef struct NpyIter_BD NpyIter_BufferData;
&(iter)->iter_flexdata + NIT_BASEOFFSETS_OFFSET(itflags, ndim, nop)))
#define NIT_OPERANDS(iter) ((PyArrayObject **)( \
&(iter)->iter_flexdata + NIT_OPERANDS_OFFSET(itflags, ndim, nop)))
-#define NIT_OPITFLAGS(iter) ( \
- &(iter)->iter_flexdata + NIT_OPITFLAGS_OFFSET(itflags, ndim, nop))
+#define NIT_OPITFLAGS(iter) ((npyiter_opitflags *)( \
+ &(iter)->iter_flexdata + NIT_OPITFLAGS_OFFSET(itflags, ndim, nop)))
#define NIT_BUFFERDATA(iter) ((NpyIter_BufferData *)( \
&(iter)->iter_flexdata + NIT_BUFFERDATA_OFFSET(itflags, ndim, nop)))
#define NIT_AXISDATA(iter) ((NpyIter_AxisData *)( \