summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--numpy/core/src/multiarray/lowlevel_strided_loops.c.src349
1 files changed, 209 insertions, 140 deletions
diff --git a/numpy/core/src/multiarray/lowlevel_strided_loops.c.src b/numpy/core/src/multiarray/lowlevel_strided_loops.c.src
index 2601acf36..153549b85 100644
--- a/numpy/core/src/multiarray/lowlevel_strided_loops.c.src
+++ b/numpy/core/src/multiarray/lowlevel_strided_loops.c.src
@@ -790,55 +790,6 @@ PyArray_GetStridedZeroPadCopyFn(npy_intp aligned,
}
}
-/*************************** DTYPE CAST FUNCTIONS *************************/
-
-/* Does a simple aligned cast */
-typedef struct {
- void *freefunc, *copyfunc;
- PyArray_VectorUnaryFunc *castfunc;
-} _strided_cast_data;
-
-/* strided cast data copy function */
-_strided_cast_data *_strided_cast_data_copy(_strided_cast_data *data)
-{
- _strided_cast_data *newdata =
- (_strided_cast_data *)PyArray_malloc(sizeof(_strided_cast_data));
- if (newdata == NULL) {
- return NULL;
- }
-
- memcpy(newdata, data, sizeof(_strided_cast_data));
-
- return newdata;
-}
-
-static void
-_aligned_strided_to_strided_cast(char *dst, npy_intp dst_stride,
- char *src, npy_intp src_stride,
- npy_intp N, npy_intp src_itemsize,
- void *data)
-{
- PyArray_VectorUnaryFunc *castfunc = ((_strided_cast_data *)data)->castfunc;
-
- while (N > 0) {
- castfunc(src, dst, 1, NULL, NULL);
- dst += dst_stride;
- src += src_stride;
- --N;
- }
-}
-
-static void
-_aligned_contig_to_contig_cast(char *dst, npy_intp NPY_UNUSED(dst_stride),
- char *src, npy_intp NPY_UNUSED(src_stride),
- npy_intp N, npy_intp NPY_UNUSED(itemsize),
- void *data)
-{
- PyArray_VectorUnaryFunc *castfunc = ((_strided_cast_data *)data)->castfunc;
-
- castfunc(src, dst, N, NULL, NULL);
-}
-
/***************** WRAP ALIGNED CONTIGUOUS TRANFSER FUNCTION **************/
/* Wraps a transfer function + data in alignment code */
@@ -938,8 +889,10 @@ _strided_to_strided_contig_align_wrap(char *dst, npy_intp dst_stride,
* data passed to 'frombuffer' is NULL.
* wrapped - contig to contig transfer function being wrapped
* wrappeddata - data for wrapped
+ *
+ * Returns NPY_SUCCEED or NPY_FAIL.
*/
-NPY_NO_EXPORT void
+NPY_NO_EXPORT int
PyArray_WrapAlignedContigTransferFunction(
npy_intp src_itemsize, npy_intp dst_itemsize,
PyArray_StridedTransferFn tobuffer,
@@ -958,6 +911,10 @@ PyArray_WrapAlignedContigTransferFunction(
/* Allocate the data, and populate it */
data = (_align_wrap_data *)PyArray_malloc(datasize);
+ if (data == NULL) {
+ PyErr_NoMemory();
+ return NPY_FAIL;
+ }
data->freefunc = (void *)&_align_wrap_data_free;
data->copyfunc = (void *)&_align_wrap_data_copy;
data->tobuffer = tobuffer;
@@ -972,6 +929,199 @@ PyArray_WrapAlignedContigTransferFunction(
/* Set the function and data */
*outstransfer = &_strided_to_strided_contig_align_wrap;
*outtransferdata = data;
+
+ return NPY_SUCCEED;
+}
+
+/*************************** DTYPE CAST FUNCTIONS *************************/
+
+/* Does a simple aligned cast */
+typedef struct {
+ void *freefunc, *copyfunc;
+ PyArray_VectorUnaryFunc *castfunc;
+ PyArrayObject *aip, *aop;
+} _strided_cast_data;
+
+/* strided cast data free function */
+void _strided_cast_data_free(_strided_cast_data *data)
+{
+ Py_DECREF(data->aip);
+ Py_DECREF(data->aop);
+ PyArray_free(data);
+}
+
+/* strided cast data copy function */
+_strided_cast_data *_strided_cast_data_copy(_strided_cast_data *data)
+{
+ _strided_cast_data *newdata =
+ (_strided_cast_data *)PyArray_malloc(sizeof(_strided_cast_data));
+ if (newdata == NULL) {
+ return NULL;
+ }
+
+ memcpy(newdata, data, sizeof(_strided_cast_data));
+ Py_INCREF(newdata->aip);
+ Py_INCREF(newdata->aop);
+
+ return newdata;
+}
+
+static void
+_aligned_strided_to_strided_cast(char *dst, npy_intp dst_stride,
+ char *src, npy_intp src_stride,
+ npy_intp N, npy_intp src_itemsize,
+ void *data)
+{
+ _strided_cast_data *d = (_strided_cast_data *)data;
+ PyArray_VectorUnaryFunc *castfunc = d->castfunc;
+ PyArrayObject *aip = d->aip, *aop = d->aop;
+
+ while (N > 0) {
+ castfunc(src, dst, 1, aip, aop);
+ dst += dst_stride;
+ src += src_stride;
+ --N;
+ }
+}
+
+static void
+_aligned_contig_to_contig_cast(char *dst, npy_intp NPY_UNUSED(dst_stride),
+ char *src, npy_intp NPY_UNUSED(src_stride),
+ npy_intp N, npy_intp NPY_UNUSED(itemsize),
+ void *data)
+{
+ _strided_cast_data *d = (_strided_cast_data *)data;
+ PyArray_VectorUnaryFunc *castfunc = d->castfunc;
+ PyArrayObject *aip = d->aip, *aop = d->aop;
+
+ castfunc(src, dst, N, aip, aop);
+}
+
+static int
+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)
+{
+ _strided_cast_data *data;
+ PyArray_VectorUnaryFunc *castfunc;
+ npy_intp shape = 1, src_itemsize = src_dtype->elsize,
+ dst_itemsize = dst_dtype->elsize;
+
+ /* Get the cast function */
+ castfunc = PyArray_GetCastFunc(src_dtype, dst_dtype->type_num);
+ if (!castfunc) {
+ *outstransfer = NULL;
+ *outtransferdata = NULL;
+ return NPY_FAIL;
+ }
+
+ /* Allocate the data for the casting */
+ data = (_strided_cast_data *)PyArray_malloc(sizeof(_strided_cast_data));
+ if (data == NULL) {
+ PyErr_NoMemory();
+ *outstransfer = NULL;
+ *outtransferdata = NULL;
+ return NPY_FAIL;
+ }
+ data->freefunc = (void*)&_strided_cast_data_free;
+ data->copyfunc = (void*)&_strided_cast_data_copy;
+ data->castfunc = castfunc;
+ Py_INCREF(src_dtype);
+ data->aip = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type, src_dtype,
+ 1, &shape, NULL, NULL, 0, NULL);
+ if (data->aip == NULL) {
+ PyArray_free(data);
+ return NPY_FAIL;
+ }
+ Py_INCREF(dst_dtype);
+ data->aop = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type, dst_dtype,
+ 1, &shape, NULL, NULL, 0, NULL);
+ if (data->aop == NULL) {
+ Py_DECREF(data->aip);
+ PyArray_free(data);
+ return NPY_FAIL;
+ }
+
+
+ /* If it's aligned and all native byte order, we're all done */
+ if (aligned && PyArray_ISNBO(src_dtype->byteorder) &&
+ PyArray_ISNBO(dst_dtype->byteorder)) {
+ /* Choose the contiguous cast if we can */
+ if (src_stride == src_itemsize && dst_stride == dst_itemsize) {
+ *outstransfer = _aligned_contig_to_contig_cast;
+ }
+ else {
+ *outstransfer = _aligned_strided_to_strided_cast;
+ }
+ *outtransferdata = data;
+
+ return NPY_SUCCEED;
+ }
+ /* Otherwise, we have to copy and/or swap to aligned temporaries */
+ else {
+ PyArray_StridedTransferFn tobuffer, frombuffer, casttransfer;
+
+ /* Get the copy/swap operation from src */
+ if (src_itemsize == 1 || PyArray_ISNBO(src_dtype->byteorder)) {
+ tobuffer = PyArray_GetStridedCopyFn(aligned,
+ src_stride, src_itemsize,
+ src_itemsize);
+ }
+ /* If it's not complex, one swap */
+ else if(src_dtype->kind != 'c') {
+ tobuffer = PyArray_GetStridedCopySwapFn(aligned,
+ src_stride, src_itemsize,
+ src_itemsize);
+ }
+ /* If not complex, a paired swap */
+ else {
+ tobuffer = PyArray_GetStridedCopySwapPairFn(aligned,
+ src_stride, src_itemsize,
+ src_itemsize);
+ }
+
+ /* Get the copy/swap operation to dst */
+ if (dst_itemsize == 1 || PyArray_ISNBO(dst_dtype->byteorder)) {
+ frombuffer = PyArray_GetStridedCopyFn(aligned,
+ dst_itemsize, dst_stride,
+ dst_itemsize);
+ }
+ /* If it's not complex, one swap */
+ else if(dst_dtype->kind != 'c') {
+ frombuffer = PyArray_GetStridedCopySwapFn(aligned,
+ dst_itemsize, dst_stride,
+ dst_itemsize);
+ }
+ /* If not complex, a paired swap */
+ else {
+ frombuffer = PyArray_GetStridedCopySwapPairFn(aligned,
+ dst_itemsize, dst_stride,
+ dst_itemsize);
+ }
+
+ if (frombuffer == NULL || tobuffer == NULL) {
+ PyArray_FreeStridedTransferData(data);
+ return NPY_FAIL;
+ }
+
+ /* Use the aligned contiguous cast */
+ casttransfer = &_aligned_contig_to_contig_cast;
+
+ /* Wrap it all up in a new transfer function + data */
+ if (PyArray_WrapAlignedContigTransferFunction(
+ src_itemsize, dst_itemsize,
+ tobuffer, frombuffer,
+ casttransfer, data,
+ outstransfer, outtransferdata) != NPY_SUCCEED) {
+ PyArray_FreeStridedTransferData(data);
+ return NPY_FAIL;
+ }
+
+ return NPY_SUCCEED;
+ }
}
/**************************** COPY 1 TO N CONTIGUOUS ************************/
@@ -1643,6 +1793,8 @@ PyArray_GetDTypeTransferFunction(int aligned,
outstransfer, outtransferdata);
}
+ /* TODO: Handle fields here */
+
/* Check for different-sized strings or unicode */
if (src_type_num == dst_type_num) switch (src_type_num) {
case NPY_STRING:
@@ -1655,101 +1807,18 @@ PyArray_GetDTypeTransferFunction(int aligned,
}
/* Check whether a simple cast and some swaps will suffice */
- if (src_type_num < NPY_OBJECT && dst_type_num < NPY_OBJECT) {
- _strided_cast_data *data;
- PyArray_VectorUnaryFunc *castfunc;
-
- /* Get the cast function */
- castfunc = PyArray_GetCastFunc(src_dtype, dst_type_num);
- if (!castfunc) {
- *outstransfer = NULL;
- *outtransferdata = NULL;
- return NPY_FAIL;
- }
-
- /* Allocate the data for the casting */
- data = (_strided_cast_data *)PyArray_malloc(sizeof(_strided_cast_data));
- if (data == NULL) {
- PyErr_NoMemory();
- *outstransfer = NULL;
- *outtransferdata = NULL;
- return NPY_FAIL;
- }
- data->freefunc = (void*)&(PyArray_free);
- data->copyfunc = (void*)&(_strided_cast_data_copy);
- data->castfunc = castfunc;
-
-
- /* If it's aligned and all native byte order, we're all done */
- if (aligned && PyArray_ISNBO(src_dtype->byteorder) &&
- PyArray_ISNBO(dst_dtype->byteorder)) {
- /* Choose the contiguous cast if we can */
- if (src_stride == src_itemsize && dst_stride == dst_itemsize) {
- *outstransfer = _aligned_contig_to_contig_cast;
- }
- else {
- *outstransfer = _aligned_strided_to_strided_cast;
- }
- *outtransferdata = data;
-
- return NPY_SUCCEED;
- }
- /* Otherwise, we have to copy and/or swap to aligned temporaries */
- else {
- PyArray_StridedTransferFn tobuffer, frombuffer, casttransfer;
-
- /* Get the copy/swap operation from src */
- if (src_itemsize == 1 || PyArray_ISNBO(src_dtype->byteorder)) {
- tobuffer = PyArray_GetStridedCopyFn(aligned,
- src_stride, src_itemsize,
- src_itemsize);
- }
- else if(!PyTypeNum_ISCOMPLEX(src_type_num)) {
- tobuffer = PyArray_GetStridedCopySwapFn(aligned,
- src_stride, src_itemsize,
- src_itemsize);
- }
- else {
- tobuffer = PyArray_GetStridedCopySwapPairFn(aligned,
- src_stride, src_itemsize,
- src_itemsize);
- }
-
- /* Get the copy/swap operation to dst */
- if (dst_itemsize == 1 || PyArray_ISNBO(dst_dtype->byteorder)) {
- frombuffer = PyArray_GetStridedCopyFn(aligned,
- dst_itemsize, dst_stride,
- dst_itemsize);
- }
- else if(!PyTypeNum_ISCOMPLEX(dst_type_num)) {
- frombuffer = PyArray_GetStridedCopySwapFn(aligned,
- dst_itemsize, dst_stride,
- dst_itemsize);
- }
- else {
- frombuffer = PyArray_GetStridedCopySwapPairFn(aligned,
- dst_itemsize, dst_stride,
- dst_itemsize);
- }
-
- /* Use the aligned contiguous cast */
- casttransfer = &_aligned_contig_to_contig_cast;
-
- /* Wrap it all up in a new transfer function + data */
- PyArray_WrapAlignedContigTransferFunction(
- src_itemsize, dst_itemsize,
- tobuffer, frombuffer,
- casttransfer, data,
- outstransfer, outtransferdata);
-
- return NPY_SUCCEED;
- }
+ if (src_type_num < NPY_NTYPES && dst_type_num < NPY_NTYPES) {
+ return get_cast_transfer_function(aligned,
+ src_stride, dst_stride,
+ src_dtype, dst_dtype,
+ move_references,
+ outstransfer, outtransferdata);
}
/* TODO check for fields & subarrays */
printf("\n");
PyObject_Print((PyObject *)src_dtype, stdout, 0);
- printf(" ");
+ printf(" -> ");
PyObject_Print((PyObject *)dst_dtype, stdout, 0);
printf("\n");