summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
authorMark Wiebe <mwwiebe@gmail.com>2011-01-16 23:47:01 -0800
committerMark Wiebe <mwwiebe@gmail.com>2011-01-17 00:02:20 -0800
commite39a70cffdd40ed2868a574803bd9535289d528d (patch)
treee230756e25895b9e3961f0d44746ff5af3018681 /numpy
parente6c3a0c9411fa0fb701261a206a2a4d002de68cd (diff)
downloadnumpy-e39a70cffdd40ed2868a574803bd9535289d528d.tar.gz
ENH: core: Add needs_api output boolean from dtype transfer
This change allows the NEEDS_PYAPI flag to be re-relaxed from the string, unicode, and void types.
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/src/multiarray/arraytypes.c.src7
-rw-r--r--numpy/core/src/multiarray/ctors.c15
-rw-r--r--numpy/core/src/multiarray/dtype_transfer.c380
-rw-r--r--numpy/core/src/multiarray/item_selection.c1
-rw-r--r--numpy/core/src/multiarray/lowlevel_strided_loops.h48
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.c2
-rw-r--r--numpy/core/src/multiarray/new_iterator.c.src26
7 files changed, 297 insertions, 182 deletions
diff --git a/numpy/core/src/multiarray/arraytypes.c.src b/numpy/core/src/multiarray/arraytypes.c.src
index 0c046ae72..c9d517c50 100644
--- a/numpy/core/src/multiarray/arraytypes.c.src
+++ b/numpy/core/src/multiarray/arraytypes.c.src
@@ -3686,12 +3686,7 @@ static PyArray_Descr @from@_Descr = {
PyArray_@from@LTR,
'@endian@',
0,
- /*
- * The *_to_(STRING|UNICODE|VOID) functions use getitem/setitem,
- * so need the API. In most cases, the API won't be needed though,
- * and it would be good to refactor things to reflect that properly.
- */
- NPY_NEEDS_PYAPI,
+ 0,
PyArray_@from@,
0,
_ALIGN(@align@),
diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c
index 7b16624b5..8eb3dec37 100644
--- a/numpy/core/src/multiarray/ctors.c
+++ b/numpy/core/src/multiarray/ctors.c
@@ -2606,6 +2606,8 @@ PyArray_CopyInto(PyArrayObject *dst, PyArrayObject *src)
char *dst_data, *src_data;
npy_intp count, dst_stride, src_stride, src_itemsize;
+ int needs_api = 0;
+
PyArray_PREPARE_TRIVIAL_PAIR_ITERATION(dst, src, count,
dst_data, src_data, dst_stride, src_stride);
@@ -2614,14 +2616,14 @@ PyArray_CopyInto(PyArrayObject *dst, PyArrayObject *src)
src_stride, dst_stride,
PyArray_DESCR(src), PyArray_DESCR(dst),
0,
- &stransfer, &transferdata) != NPY_SUCCEED) {
+ &stransfer, &transferdata,
+ &needs_api) != NPY_SUCCEED) {
return -1;
}
src_itemsize = PyArray_DESCR(src)->elsize;
- if (PyDataType_FLAGCHK(PyArray_DESCR(dst), NPY_NEEDS_PYAPI) ||
- PyDataType_FLAGCHK(PyArray_DESCR(src), NPY_NEEDS_PYAPI)) {
+ if (needs_api) {
stransfer(dst_data, dst_stride, src_data, src_stride,
count, src_itemsize, transferdata);
}
@@ -2669,6 +2671,8 @@ PyArray_CopyInto(PyArrayObject *dst, PyArrayObject *src)
countptr = NpyIter_GetInnerLoopSizePtr(iter);
src_itemsize = PyArray_DESCR(src)->elsize;
+ int needs_api = NpyIter_IterationNeedsAPI(iter);
+
/*
* Because buffering is disabled in the iterator, the inner loop
* strides will be the same throughout the iteration loop. Thus,
@@ -2680,13 +2684,14 @@ PyArray_CopyInto(PyArrayObject *dst, PyArrayObject *src)
stride[1], stride[0],
PyArray_DESCR(src), PyArray_DESCR(dst),
0,
- &stransfer, &transferdata) != NPY_SUCCEED) {
+ &stransfer, &transferdata,
+ &needs_api) != NPY_SUCCEED) {
NpyIter_Deallocate(iter);
return -1;
}
- if (NpyIter_IterationNeedsAPI(iter)) {
+ if (needs_api) {
do {
stransfer(dataptr[0], stride[0],
dataptr[1], stride[1],
diff --git a/numpy/core/src/multiarray/dtype_transfer.c b/numpy/core/src/multiarray/dtype_transfer.c
index 387637265..601cee3a3 100644
--- a/numpy/core/src/multiarray/dtype_transfer.c
+++ b/numpy/core/src/multiarray/dtype_transfer.c
@@ -26,8 +26,9 @@ static int
get_decsrcref_transfer_function(int aligned,
npy_intp src_stride,
PyArray_Descr *src_dtype,
- PyArray_StridedTransferFn **outstransfer,
- void **outtransferdata);
+ PyArray_StridedTransferFn **out_stransfer,
+ void **out_transferdata,
+ int *out_needs_api);
/*
* Returns a transfer function which zeros out the dest values.
@@ -38,8 +39,9 @@ static int
get_setdstzero_transfer_function(int aligned,
npy_intp dst_stride,
PyArray_Descr *dst_dtype,
- PyArray_StridedTransferFn **outstransfer,
- void **outtransferdata);
+ PyArray_StridedTransferFn **out_stransfer,
+ void **out_transferdata,
+ int *out_needs_api);
/*************************** COPY REFERENCES *******************************/
@@ -146,18 +148,18 @@ NPY_NO_EXPORT int
PyArray_GetStridedZeroPadCopyFn(int aligned,
npy_intp src_stride, npy_intp dst_stride,
npy_intp src_itemsize, npy_intp dst_itemsize,
- PyArray_StridedTransferFn **outstransfer,
- void **outtransferdata)
+ PyArray_StridedTransferFn **out_stransfer,
+ void **out_transferdata)
{
if (src_itemsize >= dst_itemsize) {
/* If the sizes are different, the alignment flag isn't trustworthy */
if (src_itemsize != dst_itemsize) {
aligned = 0;
}
- *outstransfer = PyArray_GetStridedCopyFn(aligned, src_stride,
+ *out_stransfer = PyArray_GetStridedCopyFn(aligned, src_stride,
dst_stride, dst_itemsize);
- *outtransferdata = NULL;
- return (*outstransfer == NULL) ? NPY_FAIL : NPY_SUCCEED;
+ *out_transferdata = NULL;
+ return (*out_stransfer == NULL) ? NPY_FAIL : NPY_SUCCEED;
}
else {
_strided_zero_pad_data *d = PyArray_malloc(
@@ -170,8 +172,8 @@ PyArray_GetStridedZeroPadCopyFn(int aligned,
d->freefunc = &PyArray_free;
d->copyfunc = &_strided_zero_pad_data_copy;
- *outstransfer = &_strided_to_strided_zero_pad_copy;
- *outtransferdata = d;
+ *out_stransfer = &_strided_to_strided_zero_pad_copy;
+ *out_transferdata = d;
return NPY_SUCCEED;
}
}
@@ -358,8 +360,8 @@ wrap_aligned_contig_transfer_function(
PyArray_StridedTransferFn *frombuffer, void *fromdata,
PyArray_StridedTransferFn *wrapped, void *wrappeddata,
int init_dest,
- PyArray_StridedTransferFn **outstransfer,
- void **outtransferdata)
+ PyArray_StridedTransferFn **out_stransfer,
+ void **out_transferdata)
{
_align_wrap_data *data;
npy_intp basedatasize, datasize;
@@ -393,12 +395,12 @@ wrap_aligned_contig_transfer_function(
/* Set the function and data */
if (init_dest) {
- *outstransfer = &_strided_to_strided_contig_align_wrap_init_dest;
+ *out_stransfer = &_strided_to_strided_contig_align_wrap_init_dest;
}
else {
- *outstransfer = &_strided_to_strided_contig_align_wrap;
+ *out_stransfer = &_strided_to_strided_contig_align_wrap;
}
- *outtransferdata = data;
+ *out_transferdata = data;
return NPY_SUCCEED;
}
@@ -451,8 +453,8 @@ wrap_copy_swap_function(int aligned,
npy_intp src_stride, npy_intp dst_stride,
PyArray_Descr *dtype,
int should_swap,
- PyArray_StridedTransferFn **outstransfer,
- void **outtransferdata)
+ PyArray_StridedTransferFn **out_stransfer,
+ void **out_transferdata)
{
_wrap_copy_swap_data *data;
npy_intp shape = 1;
@@ -461,8 +463,8 @@ wrap_copy_swap_function(int aligned,
data = (_wrap_copy_swap_data *)PyArray_malloc(sizeof(_wrap_copy_swap_data));
if (data == NULL) {
PyErr_NoMemory();
- *outstransfer = NULL;
- *outtransferdata = NULL;
+ *out_stransfer = NULL;
+ *out_transferdata = NULL;
return NPY_FAIL;
}
@@ -483,8 +485,8 @@ wrap_copy_swap_function(int aligned,
return NPY_FAIL;
}
- *outstransfer = &_strided_to_strided_wrap_copy_swap;
- *outtransferdata = data;
+ *out_stransfer = &_strided_to_strided_wrap_copy_swap;
+ *out_transferdata = data;
return NPY_SUCCEED;
}
@@ -581,8 +583,9 @@ get_cast_transfer_function(int aligned,
npy_intp src_stride, npy_intp dst_stride,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
int move_references,
- PyArray_StridedTransferFn **outstransfer,
- void **outtransferdata)
+ PyArray_StridedTransferFn **out_stransfer,
+ void **out_transferdata,
+ int *out_needs_api)
{
_strided_cast_data *data;
void *todata = NULL, *fromdata = NULL;
@@ -596,11 +599,33 @@ get_cast_transfer_function(int aligned,
return NPY_FAIL;
}
+ /* Check the data types whose casting functions use API calls */
+ switch (src_dtype->type_num) {
+ case NPY_OBJECT:
+ case NPY_STRING:
+ case NPY_UNICODE:
+ case NPY_VOID:
+ if (out_needs_api) {
+ *out_needs_api = 1;
+ }
+ break;
+ }
+ switch (dst_dtype->type_num) {
+ case NPY_OBJECT:
+ case NPY_STRING:
+ case NPY_UNICODE:
+ case NPY_VOID:
+ if (out_needs_api) {
+ *out_needs_api = 1;
+ }
+ break;
+ }
+
/* Get the cast function */
castfunc = PyArray_GetCastFunc(src_dtype, dst_dtype->type_num);
if (!castfunc) {
- *outstransfer = NULL;
- *outtransferdata = NULL;
+ *out_stransfer = NULL;
+ *out_transferdata = NULL;
return NPY_FAIL;
}
@@ -608,8 +633,8 @@ get_cast_transfer_function(int aligned,
data = (_strided_cast_data *)PyArray_malloc(sizeof(_strided_cast_data));
if (data == NULL) {
PyErr_NoMemory();
- *outstransfer = NULL;
- *outtransferdata = NULL;
+ *out_stransfer = NULL;
+ *out_transferdata = NULL;
return NPY_FAIL;
}
data->freefunc = (void*)&_strided_cast_data_free;
@@ -645,17 +670,17 @@ get_cast_transfer_function(int aligned,
PyArray_ISNBO(dst_dtype->byteorder)) {
/* Choose the contiguous cast if we can */
if (move_references && src_dtype->type_num == NPY_OBJECT) {
- *outstransfer = _aligned_strided_to_strided_cast_decref_src;
+ *out_stransfer = _aligned_strided_to_strided_cast_decref_src;
}
else {
if (src_stride == src_itemsize && dst_stride == dst_itemsize) {
- *outstransfer = _aligned_contig_to_contig_cast;
+ *out_stransfer = _aligned_contig_to_contig_cast;
}
else {
- *outstransfer = _aligned_strided_to_strided_cast;
+ *out_stransfer = _aligned_strided_to_strided_cast;
}
}
- *outtransferdata = data;
+ *out_transferdata = data;
return NPY_SUCCEED;
}
@@ -737,7 +762,7 @@ get_cast_transfer_function(int aligned,
/* If necessary, use the cast function with source decref */
if (move_references && src_dtype->type_num == NPY_OBJECT) {
- *outstransfer = _aligned_strided_to_strided_cast_decref_src;
+ *out_stransfer = _aligned_strided_to_strided_cast_decref_src;
}
/* Use the aligned contiguous cast otherwise */
else {
@@ -751,7 +776,7 @@ get_cast_transfer_function(int aligned,
frombuffer, fromdata,
casttransfer, data,
PyDataType_FLAGCHK(dst_dtype, NPY_NEEDS_INIT),
- outstransfer, outtransferdata) != NPY_SUCCEED) {
+ out_stransfer, out_transferdata) != NPY_SUCCEED) {
PyArray_FreeStridedTransferData(data);
return NPY_FAIL;
}
@@ -879,8 +904,8 @@ wrap_transfer_function_one_to_n(
void *data_finish_src,
npy_intp dst_itemsize,
npy_intp N,
- PyArray_StridedTransferFn **outstransfer,
- void **outtransferdata)
+ PyArray_StridedTransferFn **out_stransfer,
+ void **out_transferdata)
{
_one_to_n_data *data;
@@ -901,12 +926,12 @@ wrap_transfer_function_one_to_n(
data->dst_itemsize = dst_itemsize;
if (stransfer_finish_src == NULL) {
- *outstransfer = &_strided_to_strided_one_to_n;
+ *out_stransfer = &_strided_to_strided_one_to_n;
}
else {
- *outstransfer = &_strided_to_strided_one_to_n_with_finish;
+ *out_stransfer = &_strided_to_strided_one_to_n_with_finish;
}
- *outtransferdata = data;
+ *out_transferdata = data;
return NPY_SUCCEED;
}
@@ -917,8 +942,9 @@ get_one_to_n_transfer_function(int aligned,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
int move_references,
npy_intp N,
- PyArray_StridedTransferFn **outstransfer,
- void **outtransferdata)
+ PyArray_StridedTransferFn **out_stransfer,
+ void **out_transferdata,
+ int *out_needs_api)
{
PyArray_StridedTransferFn *stransfer, *stransfer_finish_src = NULL;
void *data, *data_finish_src = NULL;
@@ -933,7 +959,8 @@ get_one_to_n_transfer_function(int aligned,
0, dst_dtype->elsize,
src_dtype, dst_dtype,
0,
- &stransfer, &data) != NPY_SUCCEED) {
+ &stransfer, &data,
+ out_needs_api) != NPY_SUCCEED) {
return NPY_FAIL;
}
@@ -943,7 +970,8 @@ get_one_to_n_transfer_function(int aligned,
src_stride,
src_dtype,
&stransfer_finish_src,
- &data_finish_src) != NPY_SUCCEED) {
+ &data_finish_src,
+ out_needs_api) != NPY_SUCCEED) {
PyArray_FreeStridedTransferData(data);
return NPY_FAIL;
}
@@ -953,7 +981,7 @@ get_one_to_n_transfer_function(int aligned,
stransfer_finish_src, data_finish_src,
dst_dtype->elsize,
N,
- outstransfer, outtransferdata) != NPY_SUCCEED) {
+ out_stransfer, out_transferdata) != NPY_SUCCEED) {
PyArray_FreeStridedTransferData(data);
PyArray_FreeStridedTransferData(data_finish_src);
return NPY_FAIL;
@@ -1054,8 +1082,8 @@ wrap_transfer_function_n_to_n(
npy_intp src_stride, npy_intp dst_stride,
npy_intp src_itemsize, npy_intp dst_itemsize,
npy_intp N,
- PyArray_StridedTransferFn **outstransfer,
- void **outtransferdata)
+ PyArray_StridedTransferFn **out_stransfer,
+ void **out_transferdata)
{
_n_to_n_data *data;
@@ -1079,12 +1107,12 @@ wrap_transfer_function_n_to_n(
*/
if (src_stride == N * src_itemsize &&
dst_stride == N * dst_itemsize) {
- *outstransfer = &_contig_to_contig_n_to_n;
+ *out_stransfer = &_contig_to_contig_n_to_n;
}
else {
- *outstransfer = &_strided_to_strided_n_to_n;
+ *out_stransfer = &_strided_to_strided_n_to_n;
}
- *outtransferdata = data;
+ *out_transferdata = data;
return NPY_SUCCEED;
}
@@ -1095,8 +1123,9 @@ get_n_to_n_transfer_function(int aligned,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
int move_references,
npy_intp N,
- PyArray_StridedTransferFn **outstransfer,
- void **outtransferdata)
+ PyArray_StridedTransferFn **out_stransfer,
+ void **out_transferdata,
+ int *out_needs_api)
{
PyArray_StridedTransferFn *stransfer;
void *data;
@@ -1109,7 +1138,8 @@ get_n_to_n_transfer_function(int aligned,
src_dtype->elsize, dst_dtype->elsize,
src_dtype, dst_dtype,
move_references,
- &stransfer, &data) != NPY_SUCCEED) {
+ &stransfer, &data,
+ out_needs_api) != NPY_SUCCEED) {
return NPY_FAIL;
}
@@ -1117,8 +1147,8 @@ get_n_to_n_transfer_function(int aligned,
src_stride, dst_stride,
src_dtype->elsize, dst_dtype->elsize,
N,
- outstransfer,
- outtransferdata) != NPY_SUCCEED) {
+ out_stransfer,
+ out_transferdata) != NPY_SUCCEED) {
PyArray_FreeStridedTransferData(data);
return NPY_FAIL;
}
@@ -1307,8 +1337,9 @@ get_subarray_broadcast_transfer_function(int aligned,
npy_intp src_size, npy_intp dst_size,
PyArray_Dims src_shape, PyArray_Dims dst_shape,
int move_references,
- PyArray_StridedTransferFn **outstransfer,
- void **outtransferdata)
+ PyArray_StridedTransferFn **out_stransfer,
+ void **out_transferdata,
+ int *out_needs_api)
{
_subarray_broadcast_data *data;
npy_intp structsize, index, run, run_size, src_index, dst_index, i, ndim;
@@ -1333,7 +1364,8 @@ get_subarray_broadcast_transfer_function(int aligned,
src_dtype->elsize, dst_dtype->elsize,
src_dtype, dst_dtype,
0,
- &data->stransfer, &data->data) != NPY_SUCCEED) {
+ &data->stransfer, &data->data,
+ out_needs_api) != NPY_SUCCEED) {
PyArray_free(data);
return NPY_FAIL;
}
@@ -1351,7 +1383,8 @@ get_subarray_broadcast_transfer_function(int aligned,
src_dtype, NULL,
1,
&data->stransfer_decsrcref,
- &data->data_decsrcref) != NPY_SUCCEED) {
+ &data->data_decsrcref,
+ out_needs_api) != NPY_SUCCEED) {
PyArray_FreeStridedTransferData(data->data);
PyArray_free(data);
return NPY_FAIL;
@@ -1369,7 +1402,8 @@ get_subarray_broadcast_transfer_function(int aligned,
dst_dtype, NULL,
1,
&data->stransfer_decdstref,
- &data->data_decdstref) != NPY_SUCCEED) {
+ &data->data_decdstref,
+ out_needs_api) != NPY_SUCCEED) {
PyArray_FreeStridedTransferData(data->data);
PyArray_FreeStridedTransferData(data->data_decsrcref);
PyArray_free(data);
@@ -1469,12 +1503,12 @@ get_subarray_broadcast_transfer_function(int aligned,
if (data->stransfer_decsrcref == NULL &&
data->stransfer_decdstref == NULL) {
- *outstransfer = &_strided_to_strided_subarray_broadcast;
+ *out_stransfer = &_strided_to_strided_subarray_broadcast;
}
else {
- *outstransfer = &_strided_to_strided_subarray_broadcast_withrefs;
+ *out_stransfer = &_strided_to_strided_subarray_broadcast_withrefs;
}
- *outtransferdata = data;
+ *out_transferdata = data;
return NPY_SUCCEED;
}
@@ -1488,8 +1522,9 @@ get_subarray_transfer_function(int aligned,
npy_intp src_stride, npy_intp dst_stride,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
int move_references,
- PyArray_StridedTransferFn **outstransfer,
- void **outtransferdata)
+ PyArray_StridedTransferFn **out_stransfer,
+ void **out_transferdata,
+ int *out_needs_api)
{
PyArray_Dims src_shape = {NULL, -1}, dst_shape = {NULL, -1};
npy_intp src_size = 1, dst_size = 1;
@@ -1530,7 +1565,8 @@ get_subarray_transfer_function(int aligned,
src_stride, dst_stride,
src_dtype, dst_dtype,
move_references,
- outstransfer, outtransferdata);
+ out_stransfer, out_transferdata,
+ out_needs_api);
}
/* Copy the src value to all the dst values */
else if (src_size == 1) {
@@ -1542,7 +1578,8 @@ get_subarray_transfer_function(int aligned,
src_dtype, dst_dtype,
move_references,
dst_size,
- outstransfer, outtransferdata);
+ out_stransfer, out_transferdata,
+ out_needs_api);
}
/* If the shapes match exactly, do an n to n copy */
else if (src_shape.len == dst_shape.len &&
@@ -1556,7 +1593,8 @@ get_subarray_transfer_function(int aligned,
src_dtype, dst_dtype,
move_references,
src_size,
- outstransfer, outtransferdata);
+ out_stransfer, out_transferdata,
+ out_needs_api);
}
/*
* Copy the subarray with broadcasting, truncating, and zero-padding
@@ -1569,7 +1607,8 @@ get_subarray_transfer_function(int aligned,
src_size, dst_size,
src_shape, dst_shape,
move_references,
- outstransfer, outtransferdata);
+ out_stransfer, out_transferdata,
+ out_needs_api);
PyDimMem_FREE(src_shape.ptr);
PyDimMem_FREE(dst_shape.ptr);
@@ -1688,8 +1727,9 @@ get_fields_transfer_function(int aligned,
npy_intp src_stride, npy_intp dst_stride,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
int move_references,
- PyArray_StridedTransferFn **outstransfer,
- void **outtransferdata)
+ PyArray_StridedTransferFn **out_stransfer,
+ void **out_transferdata,
+ int *out_needs_api)
{
PyObject *names, *key, *tup, *title;
PyArray_Descr *src_fld_dtype, *dst_fld_dtype;
@@ -1729,7 +1769,8 @@ get_fields_transfer_function(int aligned,
src_dtype, dst_fld_dtype,
0,
&fields[i].stransfer,
- &fields[i].data) != NPY_SUCCEED) {
+ &fields[i].data,
+ out_needs_api) != NPY_SUCCEED) {
for (i = i-1; i >= 0; --i) {
PyArray_FreeStridedTransferData(fields[i].data);
}
@@ -1750,7 +1791,8 @@ get_fields_transfer_function(int aligned,
src_stride,
src_dtype,
&fields[field_count].stransfer,
- &fields[field_count].data) != NPY_SUCCEED) {
+ &fields[field_count].data,
+ out_needs_api) != NPY_SUCCEED) {
for (i = 0; i < field_count; ++i) {
PyArray_FreeStridedTransferData(fields[i].data);
}
@@ -1764,8 +1806,8 @@ get_fields_transfer_function(int aligned,
}
data->field_count = field_count;
- *outstransfer = &_strided_to_strided_field_transfer;
- *outtransferdata = data;
+ *out_stransfer = &_strided_to_strided_field_transfer;
+ *out_transferdata = data;
return NPY_SUCCEED;
}
@@ -1808,7 +1850,8 @@ get_fields_transfer_function(int aligned,
src_fld_dtype, dst_dtype,
move_references,
&fields[0].stransfer,
- &fields[0].data) != NPY_SUCCEED) {
+ &fields[0].data,
+ out_needs_api) != NPY_SUCCEED) {
PyArray_free(data);
return NPY_FAIL;
}
@@ -1835,7 +1878,8 @@ get_fields_transfer_function(int aligned,
src_stride,
src_fld_dtype,
&fields[field_count].stransfer,
- &fields[field_count].data) != NPY_SUCCEED) {
+ &fields[field_count].data,
+ out_needs_api) != NPY_SUCCEED) {
for (i = field_count-1; i >= 0; --i) {
PyArray_FreeStridedTransferData(fields[i].data);
}
@@ -1852,8 +1896,8 @@ get_fields_transfer_function(int aligned,
data->field_count = field_count;
- *outstransfer = &_strided_to_strided_field_transfer;
- *outtransferdata = data;
+ *out_stransfer = &_strided_to_strided_field_transfer;
+ *out_transferdata = data;
return NPY_SUCCEED;
}
@@ -1920,7 +1964,8 @@ get_fields_transfer_function(int aligned,
src_fld_dtype, dst_fld_dtype,
move_references,
&fields[i].stransfer,
- &fields[i].data) != NPY_SUCCEED) {
+ &fields[i].data,
+ out_needs_api) != NPY_SUCCEED) {
for (i = i-1; i >= 0; --i) {
PyArray_FreeStridedTransferData(fields[i].data);
}
@@ -1941,7 +1986,8 @@ get_fields_transfer_function(int aligned,
dst_stride,
dst_fld_dtype,
&fields[i].stransfer,
- &fields[i].data) != NPY_SUCCEED) {
+ &fields[i].data,
+ out_needs_api) != NPY_SUCCEED) {
for (i = i-1; i >= 0; --i) {
PyArray_FreeStridedTransferData(fields[i].data);
}
@@ -1979,7 +2025,8 @@ get_fields_transfer_function(int aligned,
src_stride,
src_fld_dtype,
&fields[field_count].stransfer,
- &fields[field_count].data) != NPY_SUCCEED) {
+ &fields[field_count].data,
+ out_needs_api) != NPY_SUCCEED) {
for (i = field_count-1; i >= 0; --i) {
PyArray_FreeStridedTransferData(fields[i].data);
}
@@ -2000,8 +2047,8 @@ get_fields_transfer_function(int aligned,
data->field_count = field_count;
- *outstransfer = &_strided_to_strided_field_transfer;
- *outtransferdata = data;
+ *out_stransfer = &_strided_to_strided_field_transfer;
+ *out_transferdata = data;
return NPY_SUCCEED;
}
@@ -2011,8 +2058,9 @@ static int
get_decsrcref_fields_transfer_function(int aligned,
npy_intp src_stride,
PyArray_Descr *src_dtype,
- PyArray_StridedTransferFn **outstransfer,
- void **outtransferdata)
+ PyArray_StridedTransferFn **out_stransfer,
+ void **out_transferdata,
+ int *out_needs_api)
{
PyObject *names, *key, *tup, *title;
PyArray_Descr *src_fld_dtype;
@@ -2047,11 +2095,15 @@ get_decsrcref_fields_transfer_function(int aligned,
return NPY_FAIL;
}
if (PyDataType_REFCHK(src_fld_dtype)) {
+ if (out_needs_api) {
+ *out_needs_api = 1;
+ }
if (get_decsrcref_transfer_function(0,
src_stride,
src_fld_dtype,
&fields[field_count].stransfer,
- &fields[field_count].data) != NPY_SUCCEED) {
+ &fields[field_count].data,
+ out_needs_api) != NPY_SUCCEED) {
for (i = field_count-1; i >= 0; --i) {
PyArray_FreeStridedTransferData(fields[i].data);
}
@@ -2067,8 +2119,8 @@ get_decsrcref_fields_transfer_function(int aligned,
data->field_count = field_count;
- *outstransfer = &_strided_to_strided_field_transfer;
- *outtransferdata = data;
+ *out_stransfer = &_strided_to_strided_field_transfer;
+ *out_transferdata = data;
return NPY_SUCCEED;
}
@@ -2077,8 +2129,9 @@ static int
get_setdestzero_fields_transfer_function(int aligned,
npy_intp dst_stride,
PyArray_Descr *dst_dtype,
- PyArray_StridedTransferFn **outstransfer,
- void **outtransferdata)
+ PyArray_StridedTransferFn **out_stransfer,
+ void **out_transferdata,
+ int *out_needs_api)
{
PyObject *names, *key, *tup, *title;
PyArray_Descr *dst_fld_dtype;
@@ -2115,7 +2168,8 @@ get_setdestzero_fields_transfer_function(int aligned,
dst_stride,
dst_fld_dtype,
&fields[i].stransfer,
- &fields[i].data) != NPY_SUCCEED) {
+ &fields[i].data,
+ out_needs_api) != NPY_SUCCEED) {
for (i = i-1; i >= 0; --i) {
PyArray_FreeStridedTransferData(fields[i].data);
}
@@ -2129,8 +2183,8 @@ get_setdestzero_fields_transfer_function(int aligned,
data->field_count = field_count;
- *outstransfer = &_strided_to_strided_field_transfer;
- *outtransferdata = data;
+ *out_stransfer = &_strided_to_strided_field_transfer;
+ *out_transferdata = data;
return NPY_SUCCEED;
}
@@ -2217,8 +2271,9 @@ NPY_NO_EXPORT int
get_setdstzero_transfer_function(int aligned,
npy_intp dst_stride,
PyArray_Descr *dst_dtype,
- PyArray_StridedTransferFn **outstransfer,
- void **outtransferdata)
+ PyArray_StridedTransferFn **out_stransfer,
+ void **out_transferdata,
+ int *out_needs_api)
{
_dst_memset_zero_data *data;
@@ -2236,19 +2291,23 @@ get_setdstzero_transfer_function(int aligned,
data->dst_itemsize = dst_dtype->elsize;
if (dst_stride == data->dst_itemsize) {
- *outstransfer = &_null_to_contig_memset_zero;
+ *out_stransfer = &_null_to_contig_memset_zero;
}
else {
- *outstransfer = &_null_to_strided_memset_zero;
+ *out_stransfer = &_null_to_strided_memset_zero;
}
- *outtransferdata = data;
+ *out_transferdata = data;
return NPY_SUCCEED;
}
/* If it's exactly one reference, use the decref function */
else if (dst_dtype->type_num == NPY_OBJECT) {
- *outstransfer = &_null_to_strided_reference_setzero;
- *outtransferdata = NULL;
+ if (out_needs_api) {
+ *out_needs_api = 1;
+ }
+
+ *out_stransfer = &_null_to_strided_reference_setzero;
+ *out_transferdata = NULL;
return NPY_SUCCEED;
}
@@ -2259,6 +2318,10 @@ get_setdstzero_transfer_function(int aligned,
PyArray_StridedTransferFn *stransfer;
void *data;
+ if (out_needs_api) {
+ *out_needs_api = 1;
+ }
+
if (!(PyArray_IntpConverter(dst_dtype->subarray->shape,
&dst_shape))) {
PyErr_SetString(PyExc_ValueError,
@@ -2272,7 +2335,8 @@ get_setdstzero_transfer_function(int aligned,
if (get_setdstzero_transfer_function(aligned,
dst_dtype->subarray->base->elsize,
dst_dtype->subarray->base,
- &stransfer, &data) != NPY_SUCCEED) {
+ &stransfer, &data,
+ out_needs_api) != NPY_SUCCEED) {
return NPY_FAIL;
}
@@ -2280,7 +2344,7 @@ get_setdstzero_transfer_function(int aligned,
0, dst_stride,
0, dst_dtype->subarray->base->elsize,
dst_size,
- outstransfer, outtransferdata) != NPY_SUCCEED) {
+ out_stransfer, out_transferdata) != NPY_SUCCEED) {
PyArray_FreeStridedTransferData(data);
return NPY_FAIL;
}
@@ -2289,10 +2353,15 @@ get_setdstzero_transfer_function(int aligned,
}
/* If there are fields, need to do each field */
else if (PyDataType_HASFIELDS(dst_dtype)) {
+ if (out_needs_api) {
+ *out_needs_api = 1;
+ }
+
return get_setdestzero_fields_transfer_function(aligned,
dst_stride, dst_dtype,
- outstransfer,
- outtransferdata);
+ out_stransfer,
+ out_transferdata,
+ out_needs_api);
}
}
@@ -2332,20 +2401,25 @@ NPY_NO_EXPORT int
get_decsrcref_transfer_function(int aligned,
npy_intp src_stride,
PyArray_Descr *src_dtype,
- PyArray_StridedTransferFn **outstransfer,
- void **outtransferdata)
+ PyArray_StridedTransferFn **out_stransfer,
+ void **out_transferdata,
+ int *out_needs_api)
{
/* If there are no references, it's a nop */
if (!PyDataType_REFCHK(src_dtype)) {
- *outstransfer = &_dec_src_ref_nop;
- *outtransferdata = NULL;
+ *out_stransfer = &_dec_src_ref_nop;
+ *out_transferdata = NULL;
return NPY_SUCCEED;
}
/* If it's a single reference, it's one decref */
else if (src_dtype->type_num == NPY_OBJECT) {
- *outstransfer = &_strided_to_null_dec_src_ref_reference;
- *outtransferdata = NULL;
+ if (out_needs_api) {
+ *out_needs_api = 1;
+ }
+
+ *out_stransfer = &_strided_to_null_dec_src_ref_reference;
+ *out_transferdata = NULL;
return NPY_SUCCEED;
}
@@ -2356,6 +2430,10 @@ get_decsrcref_transfer_function(int aligned,
PyArray_StridedTransferFn *stransfer;
void *data;
+ if (out_needs_api) {
+ *out_needs_api = 1;
+ }
+
if (!(PyArray_IntpConverter(src_dtype->subarray->shape,
&src_shape))) {
PyErr_SetString(PyExc_ValueError,
@@ -2369,7 +2447,8 @@ get_decsrcref_transfer_function(int aligned,
if (get_decsrcref_transfer_function(aligned,
src_dtype->subarray->base->elsize,
src_dtype->subarray->base,
- &stransfer, &data) != NPY_SUCCEED) {
+ &stransfer, &data,
+ out_needs_api) != NPY_SUCCEED) {
return NPY_FAIL;
}
@@ -2377,7 +2456,7 @@ get_decsrcref_transfer_function(int aligned,
src_stride, 0,
src_dtype->subarray->base->elsize, 0,
src_size,
- outstransfer, outtransferdata) != NPY_SUCCEED) {
+ out_stransfer, out_transferdata) != NPY_SUCCEED) {
PyArray_FreeStridedTransferData(data);
return NPY_FAIL;
}
@@ -2386,10 +2465,15 @@ get_decsrcref_transfer_function(int aligned,
}
/* If there are fields, need to do each field */
else {
+ if (out_needs_api) {
+ *out_needs_api = 1;
+ }
+
return get_decsrcref_fields_transfer_function(aligned,
src_stride, src_dtype,
- outstransfer,
- outtransferdata);
+ out_stransfer,
+ out_transferdata,
+ out_needs_api);
}
}
@@ -2400,8 +2484,9 @@ PyArray_GetDTypeTransferFunction(int aligned,
npy_intp src_stride, npy_intp dst_stride,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
int move_references,
- PyArray_StridedTransferFn **outstransfer,
- void **outtransferdata)
+ PyArray_StridedTransferFn **out_stransfer,
+ void **out_transferdata,
+ int *out_needs_api)
{
npy_intp src_itemsize, dst_itemsize;
int src_type_num, dst_type_num;
@@ -2423,11 +2508,12 @@ PyArray_GetDTypeTransferFunction(int aligned,
return get_decsrcref_transfer_function(aligned,
src_dtype->elsize,
src_dtype,
- outstransfer, outtransferdata);
+ out_stransfer, out_transferdata,
+ out_needs_api);
}
else {
- *outstransfer = &_dec_src_ref_nop;
- *outtransferdata = NULL;
+ *out_stransfer = &_dec_src_ref_nop;
+ *out_transferdata = NULL;
return NPY_SUCCEED;
}
}
@@ -2435,7 +2521,8 @@ PyArray_GetDTypeTransferFunction(int aligned,
return get_setdstzero_transfer_function(aligned,
dst_dtype->elsize,
dst_dtype,
- outstransfer, outtransferdata);
+ out_stransfer, out_transferdata,
+ out_needs_api);
}
src_itemsize = src_dtype->elsize;
@@ -2459,10 +2546,10 @@ PyArray_GetDTypeTransferFunction(int aligned,
* which holds the strongest alignment value for all
* the data which will be used.
*/
- *outstransfer = PyArray_GetStridedCopyFn(0,
+ *out_stransfer = PyArray_GetStridedCopyFn(0,
src_stride, dst_stride,
src_dtype->elsize);
- *outtransferdata = NULL;
+ *out_transferdata = NULL;
return NPY_SUCCEED;
}
@@ -2482,7 +2569,8 @@ PyArray_GetDTypeTransferFunction(int aligned,
src_stride, dst_stride,
src_dtype, dst_dtype,
move_references,
- outstransfer, outtransferdata);
+ out_stransfer, out_transferdata,
+ out_needs_api);
}
else {
return wrap_copy_swap_function(aligned,
@@ -2490,7 +2578,7 @@ PyArray_GetDTypeTransferFunction(int aligned,
src_dtype,
PyArray_ISNBO(src_dtype->byteorder) !=
PyArray_ISNBO(dst_dtype->byteorder),
- outstransfer, outtransferdata);
+ out_stransfer, out_transferdata);
}
@@ -2501,19 +2589,22 @@ PyArray_GetDTypeTransferFunction(int aligned,
case NPY_VOID:
case NPY_STRING:
case NPY_UNICODE:
- *outstransfer = PyArray_GetStridedCopyFn(0,
+ *out_stransfer = PyArray_GetStridedCopyFn(0,
src_stride, dst_stride,
src_itemsize);
- *outtransferdata = NULL;
+ *out_transferdata = NULL;
return NPY_SUCCEED;
case NPY_OBJECT:
+ if (out_needs_api) {
+ *out_needs_api = 1;
+ }
if (move_references) {
- *outstransfer = &_strided_to_strided_move_references;
- *outtransferdata = NULL;
+ *out_stransfer = &_strided_to_strided_move_references;
+ *out_transferdata = NULL;
}
else {
- *outstransfer = &_strided_to_strided_copy_references;
- *outtransferdata = NULL;
+ *out_stransfer = &_strided_to_strided_copy_references;
+ *out_transferdata = NULL;
}
return NPY_SUCCEED;
}
@@ -2521,27 +2612,27 @@ PyArray_GetDTypeTransferFunction(int aligned,
/* This is a straight copy */
if (src_itemsize == 1 || PyArray_ISNBO(src_dtype->byteorder) ==
PyArray_ISNBO(dst_dtype->byteorder)) {
- *outstransfer = PyArray_GetStridedCopyFn(aligned,
+ *out_stransfer = PyArray_GetStridedCopyFn(aligned,
src_stride, dst_stride,
src_itemsize);
- *outtransferdata = NULL;
- return (*outstransfer == NULL) ? NPY_FAIL : NPY_SUCCEED;
+ *out_transferdata = NULL;
+ return (*out_stransfer == NULL) ? NPY_FAIL : NPY_SUCCEED;
}
/* This is a straight copy + byte swap */
else if (!PyTypeNum_ISCOMPLEX(src_type_num)) {
- *outstransfer = PyArray_GetStridedCopySwapFn(aligned,
+ *out_stransfer = PyArray_GetStridedCopySwapFn(aligned,
src_stride, dst_stride,
src_itemsize);
- *outtransferdata = NULL;
- return (*outstransfer == NULL) ? NPY_FAIL : NPY_SUCCEED;
+ *out_transferdata = NULL;
+ return (*out_stransfer == NULL) ? NPY_FAIL : NPY_SUCCEED;
}
/* This is a straight copy + element pair byte swap */
else {
- *outstransfer = PyArray_GetStridedCopySwapPairFn(aligned,
+ *out_stransfer = PyArray_GetStridedCopySwapPairFn(aligned,
src_stride, dst_stride,
src_itemsize);
- *outtransferdata = NULL;
- return (*outstransfer == NULL) ? NPY_FAIL : NPY_SUCCEED;
+ *out_transferdata = NULL;
+ return (*out_stransfer == NULL) ? NPY_FAIL : NPY_SUCCEED;
}
}
@@ -2551,7 +2642,8 @@ PyArray_GetDTypeTransferFunction(int aligned,
src_stride, dst_stride,
src_dtype, dst_dtype,
move_references,
- outstransfer, outtransferdata);
+ out_stransfer, out_transferdata,
+ out_needs_api);
}
/* Handle fields */
@@ -2561,7 +2653,8 @@ PyArray_GetDTypeTransferFunction(int aligned,
src_stride, dst_stride,
src_dtype, dst_dtype,
move_references,
- outstransfer, outtransferdata);
+ out_stransfer, out_transferdata,
+ out_needs_api);
}
/* Check for different-sized strings, unicodes, or voids */
@@ -2572,7 +2665,7 @@ PyArray_GetDTypeTransferFunction(int aligned,
return PyArray_GetStridedZeroPadCopyFn(0,
src_stride, dst_stride,
src_dtype->elsize, dst_dtype->elsize,
- outstransfer, outtransferdata);
+ out_stransfer, out_transferdata);
}
/* Otherwise a cast is necessary */
@@ -2580,6 +2673,7 @@ PyArray_GetDTypeTransferFunction(int aligned,
src_stride, dst_stride,
src_dtype, dst_dtype,
move_references,
- outstransfer, outtransferdata);
+ out_stransfer, out_transferdata,
+ out_needs_api);
}
diff --git a/numpy/core/src/multiarray/item_selection.c b/numpy/core/src/multiarray/item_selection.c
index 68dbb4293..cc8e6aa8a 100644
--- a/numpy/core/src/multiarray/item_selection.c
+++ b/numpy/core/src/multiarray/item_selection.c
@@ -1690,7 +1690,6 @@ PyArray_Compress(PyArrayObject *self, PyObject *condition, int axis,
NPY_NO_EXPORT npy_intp
PyArray_CountNonzero(PyArrayObject *self)
{
- int ndim = PyArray_NDIM(self);
PyArray_NonzeroFunc *nonzero = self->descr->f->nonzero;
char *data;
npy_intp stride, count;
diff --git a/numpy/core/src/multiarray/lowlevel_strided_loops.h b/numpy/core/src/multiarray/lowlevel_strided_loops.h
index 353f87889..e3427e3c6 100644
--- a/numpy/core/src/multiarray/lowlevel_strided_loops.h
+++ b/numpy/core/src/multiarray/lowlevel_strided_loops.h
@@ -115,25 +115,42 @@ PyArray_GetStridedZeroPadCopyFn(int aligned,
* it must be deallocated with the ``PyArray_FreeStridedTransferData``
* function when the transfer function is no longer required.
*
- * For information on the 'aligned', 'src_stride' and 'dst_stride' parameters
- * see above.
- *
- * If move_references is 1, and 'src_dtype' has references,
- * the source references will get a DECREF after the reference value is
- * cast to the dest type.
+ * 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
+ * ``PyArray_FreeStridedTransferData`` 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.
*
- * If you pass NULL to src_dtype, you get a transfer function which does
- * not touch the src values, and sets the dst values to zeros.
- *
- * If you pass NULL to dst_dtype, you either get a no-op, or if you
- * also set move_references to 1, you get a transfer function which
- * decrements the references in src.
- *
* Returns NPY_SUCCEED or NPY_FAIL.
*/
NPY_NO_EXPORT int
@@ -141,8 +158,9 @@ PyArray_GetDTypeTransferFunction(int aligned,
npy_intp src_stride, npy_intp dst_stride,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
int move_references,
- PyArray_StridedTransferFn **outstransfer,
- void **outtransferdata);
+ PyArray_StridedTransferFn **out_stransfer,
+ void **out_transferdata,
+ int *out_needs_api);
/*
* These two functions copy or convert the data of an n-dimensional array
diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c
index 95f706389..a70bd4657 100644
--- a/numpy/core/src/multiarray/multiarraymodule.c
+++ b/numpy/core/src/multiarray/multiarraymodule.c
@@ -1735,7 +1735,7 @@ array_count_nonzero(PyObject *NPY_UNUSED(self), PyObject *args)
return NULL;
}
- array = PyArray_FromAny(array_in, NULL, 0, 0, 0, NULL);
+ array = (PyArrayObject *)PyArray_FromAny(array_in, NULL, 0, 0, 0, NULL);
if (array == NULL) {
return NULL;
}
diff --git a/numpy/core/src/multiarray/new_iterator.c.src b/numpy/core/src/multiarray/new_iterator.c.src
index 63e88e3cd..05a187d53 100644
--- a/numpy/core/src/multiarray/new_iterator.c.src
+++ b/numpy/core/src/multiarray/new_iterator.c.src
@@ -586,15 +586,10 @@ NpyIter_MultiNew(npy_intp niter, PyArrayObject **op_in, npy_uint32 flags,
*/
if (flags&NPY_ITER_REFS_OK) {
for (iiter = 0; iiter < niter; ++iiter) {
- PyArray_Descr *odt = PyArray_DESCR(op[iiter]),
- *rdt = op_dtype[iiter];
- if (((odt->flags&(NPY_ITEM_REFCOUNT|
- NPY_ITEM_IS_POINTER|
- NPY_NEEDS_PYAPI)) != 0) ||
- (odt != rdt &&
- ((rdt->flags&(NPY_ITEM_REFCOUNT|
+ PyArray_Descr *rdt = op_dtype[iiter];
+ if ((rdt->flags&(NPY_ITEM_REFCOUNT|
NPY_ITEM_IS_POINTER|
- NPY_NEEDS_PYAPI))) != 0)) {
+ NPY_NEEDS_PYAPI)) != 0) {
/* Iteration needs API access */
NIT_ITFLAGS(iter) |= NPY_ITFLAG_NEEDSAPI;
}
@@ -4216,6 +4211,7 @@ npyiter_allocate_transfer_functions(NpyIter *iter)
PyArray_StridedTransferFn *stransfer = NULL;
void *transferdata = NULL;
+ int needs_api = 0;
for (iiter = 0; iiter < niter; ++iiter) {
char flags = op_itflags[iiter];
@@ -4236,7 +4232,8 @@ npyiter_allocate_transfer_functions(NpyIter *iter)
op_dtype[iiter],
move_references,
&stransfer,
- &transferdata) != NPY_SUCCEED) {
+ &transferdata,
+ &needs_api) != NPY_SUCCEED) {
goto fail;
}
readtransferfn[iiter] = stransfer;
@@ -4255,7 +4252,8 @@ npyiter_allocate_transfer_functions(NpyIter *iter)
PyArray_DESCR(op[iiter]),
move_references,
&stransfer,
- &transferdata) != NPY_SUCCEED) {
+ &transferdata,
+ &needs_api) != NPY_SUCCEED) {
goto fail;
}
writetransferfn[iiter] = stransfer;
@@ -4274,7 +4272,8 @@ npyiter_allocate_transfer_functions(NpyIter *iter)
op_dtype[iiter], NULL,
1,
&stransfer,
- &transferdata) != NPY_SUCCEED) {
+ &transferdata,
+ &needs_api) != NPY_SUCCEED) {
goto fail;
}
writetransferfn[iiter] = stransfer;
@@ -4290,6 +4289,11 @@ npyiter_allocate_transfer_functions(NpyIter *iter)
}
}
+ /* If any of the dtype transfer functions needed the API, flag it */
+ if (needs_api) {
+ NIT_ITFLAGS(iter) |= NPY_ITFLAG_NEEDSAPI;
+ }
+
return 1;
fail: