summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.c83
-rw-r--r--numpy/core/tests/test_api.py28
2 files changed, 61 insertions, 50 deletions
diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c
index 28c596d9c..f121f6147 100644
--- a/numpy/core/src/multiarray/multiarraymodule.c
+++ b/numpy/core/src/multiarray/multiarraymodule.c
@@ -883,68 +883,51 @@ PyArray_MatrixProduct(PyObject *op1, PyObject *op2)
}
/*NUMPY_API
- * Fast Copy and Transpose
+ * Copy and Transpose
+ *
+ * Could deprecate this function, as there isn't a speed benefit over
+ * calling Transpose and then Copy.
*/
NPY_NO_EXPORT PyObject *
PyArray_CopyAndTranspose(PyObject *op)
{
- PyObject *ret, *arr;
- int nd;
- npy_intp dims[2];
- npy_intp i,j;
- int elsize, str2;
- char *iptr;
- char *optr;
+ PyArrayObject *arr, *tmp, *ret;
+ int i;
+ npy_intp new_axes_values[NPY_MAXDIMS];
+ PyArray_Dims new_axes;
- /* make sure it is well-behaved */
- arr = PyArray_FromAny(op, NULL, 0, 0, CARRAY, NULL);
+ /* Make sure we have an array */
+ arr = (PyArrayObject *)PyArray_FromAny(op, NULL, 0, 0, 0, NULL);
if (arr == NULL) {
return NULL;
}
- nd = PyArray_NDIM(arr);
- if (nd == 1) {
- /* we will give in to old behavior */
- ret = PyArray_Copy((PyArrayObject *)arr);
- Py_DECREF(arr);
- return ret;
- }
- else if (nd != 2) {
- Py_DECREF(arr);
- PyErr_SetString(PyExc_ValueError,
- "only 2-d arrays are allowed");
- return NULL;
- }
- /* Now construct output array */
- dims[0] = PyArray_DIM(arr,1);
- dims[1] = PyArray_DIM(arr,0);
- elsize = PyArray_ITEMSIZE(arr);
- Py_INCREF(PyArray_DESCR(arr));
- ret = PyArray_NewFromDescr(Py_TYPE(arr),
- PyArray_DESCR(arr),
- 2, dims,
- NULL, NULL, 0, arr);
- if (ret == NULL) {
- Py_DECREF(arr);
- return NULL;
- }
+ if (PyArray_NDIM(arr) > 1) {
+ /* Set up the transpose operation */
+ new_axes.len = PyArray_NDIM(arr);
+ for (i = 0; i < new_axes.len; ++i) {
+ new_axes_values[i] = new_axes.len - i - 1;
+ }
+ new_axes.ptr = new_axes_values;
- /* do 2-d loop */
- NPY_BEGIN_ALLOW_THREADS;
- optr = PyArray_DATA(ret);
- str2 = elsize*dims[0];
- for (i = 0; i < dims[0]; i++) {
- iptr = PyArray_BYTES(arr) + i*elsize;
- for (j = 0; j < dims[1]; j++) {
- /* optr[i,j] = iptr[j,i] */
- memcpy(optr, iptr, elsize);
- optr += elsize;
- iptr += str2;
+ /* Do the transpose (always returns a view) */
+ tmp = (PyArrayObject *)PyArray_Transpose(arr, &new_axes);
+ if (tmp == NULL) {
+ Py_DECREF(arr);
+ return NULL;
}
}
- NPY_END_ALLOW_THREADS;
- Py_DECREF(arr);
- return ret;
+ else {
+ tmp = arr;
+ arr = NULL;
+ }
+
+ /* TODO: Change this to NPY_KEEPORDER for NumPy 2.0 */
+ ret = (PyArrayObject *)PyArray_NewCopy(tmp, NPY_CORDER);
+
+ Py_XDECREF(arr);
+ Py_DECREF(tmp);
+ return (PyObject *)ret;
}
/*
diff --git a/numpy/core/tests/test_api.py b/numpy/core/tests/test_api.py
new file mode 100644
index 000000000..255ef4565
--- /dev/null
+++ b/numpy/core/tests/test_api.py
@@ -0,0 +1,28 @@
+import sys
+
+import numpy as np
+from numpy.testing import *
+from numpy.testing.utils import WarningManager
+import warnings
+
+def test_fastCopyAndTranspose():
+ # 0D array
+ a = np.array(2)
+ b = np.fastCopyAndTranspose(a)
+ assert_equal(b, a.T)
+ assert_(b.flags.owndata)
+
+ # 1D array
+ a = np.array([3,2,7,0])
+ b = np.fastCopyAndTranspose(a)
+ assert_equal(b, a.T)
+ assert_(b.flags.owndata)
+
+ # 2D array
+ a = np.arange(6).reshape(2,3)
+ b = np.fastCopyAndTranspose(a)
+ assert_equal(b, a.T)
+ assert_(b.flags.owndata)
+
+if __name__ == "__main__":
+ run_module_suite()