summaryrefslogtreecommitdiff
path: root/numpy/core/src/arraygetset.c
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/core/src/arraygetset.c')
-rw-r--r--numpy/core/src/arraygetset.c882
1 files changed, 882 insertions, 0 deletions
diff --git a/numpy/core/src/arraygetset.c b/numpy/core/src/arraygetset.c
new file mode 100644
index 000000000..2d69f29ba
--- /dev/null
+++ b/numpy/core/src/arraygetset.c
@@ -0,0 +1,882 @@
+/* Array Descr Object */
+
+#define PY_SSIZE_T_CLEAN
+#include <Python.h>
+#include "structmember.h"
+
+#define _MULTIARRAYMODULE
+#define NPY_NO_PREFIX
+#include "numpy/arrayobject.h"
+
+#include "arrayobject.h"
+#include "arraydescr.h"
+#include "arraygetset.h"
+
+/******************* array attribute get and set routines ******************/
+
+static PyObject *
+array_ndim_get(PyArrayObject *self)
+{
+ return PyInt_FromLong(self->nd);
+}
+
+static PyObject *
+array_flags_get(PyArrayObject *self)
+{
+ return PyArray_NewFlagsObject((PyObject *)self);
+}
+
+static PyObject *
+array_shape_get(PyArrayObject *self)
+{
+ return PyArray_IntTupleFromIntp(self->nd, self->dimensions);
+}
+
+
+static int
+array_shape_set(PyArrayObject *self, PyObject *val)
+{
+ int nd;
+ PyObject *ret;
+
+ /* Assumes C-order */
+ ret = PyArray_Reshape(self, val);
+ if (ret == NULL) {
+ return -1;
+ }
+ if (PyArray_DATA(ret) != PyArray_DATA(self)) {
+ Py_DECREF(ret);
+ PyErr_SetString(PyExc_AttributeError,
+ "incompatible shape for a non-contiguous "\
+ "array");
+ return -1;
+ }
+
+ /* Free old dimensions and strides */
+ PyDimMem_FREE(self->dimensions);
+ nd = PyArray_NDIM(ret);
+ self->nd = nd;
+ if (nd > 0) {
+ /* create new dimensions and strides */
+ self->dimensions = PyDimMem_NEW(2*nd);
+ if (self->dimensions == NULL) {
+ Py_DECREF(ret);
+ PyErr_SetString(PyExc_MemoryError,"");
+ return -1;
+ }
+ self->strides = self->dimensions + nd;
+ memcpy(self->dimensions, PyArray_DIMS(ret), nd*sizeof(intp));
+ memcpy(self->strides, PyArray_STRIDES(ret), nd*sizeof(intp));
+ }
+ else {
+ self->dimensions = NULL;
+ self->strides = NULL;
+ }
+ Py_DECREF(ret);
+ PyArray_UpdateFlags(self, CONTIGUOUS | FORTRAN);
+ return 0;
+}
+
+
+static PyObject *
+array_strides_get(PyArrayObject *self)
+{
+ return PyArray_IntTupleFromIntp(self->nd, self->strides);
+}
+
+static int
+array_strides_set(PyArrayObject *self, PyObject *obj)
+{
+ PyArray_Dims newstrides = {NULL, 0};
+ PyArrayObject *new;
+ intp numbytes = 0;
+ intp offset = 0;
+ Py_ssize_t buf_len;
+ char *buf;
+
+ if (!PyArray_IntpConverter(obj, &newstrides) ||
+ newstrides.ptr == NULL) {
+ PyErr_SetString(PyExc_TypeError, "invalid strides");
+ return -1;
+ }
+ if (newstrides.len != self->nd) {
+ PyErr_Format(PyExc_ValueError, "strides must be " \
+ " same length as shape (%d)", self->nd);
+ goto fail;
+ }
+ new = self;
+ while(new->base && PyArray_Check(new->base)) {
+ new = (PyArrayObject *)(new->base);
+ }
+ /*
+ * Get the available memory through the buffer interface on
+ * new->base or if that fails from the current new
+ */
+ if (new->base && PyObject_AsReadBuffer(new->base,
+ (const void **)&buf,
+ &buf_len) >= 0) {
+ offset = self->data - buf;
+ numbytes = buf_len + offset;
+ }
+ else {
+ PyErr_Clear();
+ numbytes = PyArray_MultiplyList(new->dimensions,
+ new->nd)*new->descr->elsize;
+ offset = self->data - new->data;
+ }
+
+ if (!PyArray_CheckStrides(self->descr->elsize, self->nd, numbytes,
+ offset,
+ self->dimensions, newstrides.ptr)) {
+ PyErr_SetString(PyExc_ValueError, "strides is not "\
+ "compatible with available memory");
+ goto fail;
+ }
+ memcpy(self->strides, newstrides.ptr, sizeof(intp)*newstrides.len);
+ PyArray_UpdateFlags(self, CONTIGUOUS | FORTRAN);
+ PyDimMem_FREE(newstrides.ptr);
+ return 0;
+
+ fail:
+ PyDimMem_FREE(newstrides.ptr);
+ return -1;
+}
+
+
+
+static PyObject *
+array_priority_get(PyArrayObject *self)
+{
+ if (PyArray_CheckExact(self)) {
+ return PyFloat_FromDouble(PyArray_PRIORITY);
+ }
+ else {
+ return PyFloat_FromDouble(PyArray_SUBTYPE_PRIORITY);
+ }
+}
+
+static PyObject *
+array_typestr_get(PyArrayObject *self)
+{
+ return arraydescr_protocol_typestr_get(self->descr);
+}
+
+static PyObject *
+array_descr_get(PyArrayObject *self)
+{
+ Py_INCREF(self->descr);
+ return (PyObject *)self->descr;
+}
+
+static PyObject *
+array_protocol_descr_get(PyArrayObject *self)
+{
+ PyObject *res;
+ PyObject *dobj;
+
+ res = arraydescr_protocol_descr_get(self->descr);
+ if (res) {
+ return res;
+ }
+ PyErr_Clear();
+
+ /* get default */
+ dobj = PyTuple_New(2);
+ if (dobj == NULL) {
+ return NULL;
+ }
+ PyTuple_SET_ITEM(dobj, 0, PyString_FromString(""));
+ PyTuple_SET_ITEM(dobj, 1, array_typestr_get(self));
+ res = PyList_New(1);
+ if (res == NULL) {
+ Py_DECREF(dobj);
+ return NULL;
+ }
+ PyList_SET_ITEM(res, 0, dobj);
+ return res;
+}
+
+static PyObject *
+array_protocol_strides_get(PyArrayObject *self)
+{
+ if PyArray_ISCONTIGUOUS(self) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ return PyArray_IntTupleFromIntp(self->nd, self->strides);
+}
+
+
+
+static PyObject *
+array_dataptr_get(PyArrayObject *self)
+{
+ return Py_BuildValue("NO",
+ PyLong_FromVoidPtr(self->data),
+ (self->flags & WRITEABLE ? Py_False :
+ Py_True));
+}
+
+static PyObject *
+array_ctypes_get(PyArrayObject *self)
+{
+ PyObject *_numpy_internal;
+ PyObject *ret;
+ _numpy_internal = PyImport_ImportModule("numpy.core._internal");
+ if (_numpy_internal == NULL) {
+ return NULL;
+ }
+ ret = PyObject_CallMethod(_numpy_internal, "_ctypes", "ON", self,
+ PyLong_FromVoidPtr(self->data));
+ Py_DECREF(_numpy_internal);
+ return ret;
+}
+
+static PyObject *
+array_interface_get(PyArrayObject *self)
+{
+ PyObject *dict;
+ PyObject *obj;
+
+ dict = PyDict_New();
+ if (dict == NULL) {
+ return NULL;
+ }
+
+ /* dataptr */
+ obj = array_dataptr_get(self);
+ PyDict_SetItemString(dict, "data", obj);
+ Py_DECREF(obj);
+
+ obj = array_protocol_strides_get(self);
+ PyDict_SetItemString(dict, "strides", obj);
+ Py_DECREF(obj);
+
+ obj = array_protocol_descr_get(self);
+ PyDict_SetItemString(dict, "descr", obj);
+ Py_DECREF(obj);
+
+ obj = arraydescr_protocol_typestr_get(self->descr);
+ PyDict_SetItemString(dict, "typestr", obj);
+ Py_DECREF(obj);
+
+ obj = array_shape_get(self);
+ PyDict_SetItemString(dict, "shape", obj);
+ Py_DECREF(obj);
+
+ obj = PyInt_FromLong(3);
+ PyDict_SetItemString(dict, "version", obj);
+ Py_DECREF(obj);
+
+ return dict;
+}
+
+static PyObject *
+array_data_get(PyArrayObject *self)
+{
+ intp nbytes;
+ if (!(PyArray_ISONESEGMENT(self))) {
+ PyErr_SetString(PyExc_AttributeError, "cannot get single-"\
+ "segment buffer for discontiguous array");
+ return NULL;
+ }
+ nbytes = PyArray_NBYTES(self);
+ if PyArray_ISWRITEABLE(self) {
+ return PyBuffer_FromReadWriteObject((PyObject *)self, 0, (Py_ssize_t) nbytes);
+ }
+ else {
+ return PyBuffer_FromObject((PyObject *)self, 0, (Py_ssize_t) nbytes);
+ }
+}
+
+static int
+array_data_set(PyArrayObject *self, PyObject *op)
+{
+ void *buf;
+ Py_ssize_t buf_len;
+ int writeable=1;
+
+ if (PyObject_AsWriteBuffer(op, &buf, &buf_len) < 0) {
+ writeable = 0;
+ if (PyObject_AsReadBuffer(op, (const void **)&buf, &buf_len) < 0) {
+ PyErr_SetString(PyExc_AttributeError,
+ "object does not have single-segment " \
+ "buffer interface");
+ return -1;
+ }
+ }
+ if (!PyArray_ISONESEGMENT(self)) {
+ PyErr_SetString(PyExc_AttributeError, "cannot set single-" \
+ "segment buffer for discontiguous array");
+ return -1;
+ }
+ if (PyArray_NBYTES(self) > buf_len) {
+ PyErr_SetString(PyExc_AttributeError, "not enough data for array");
+ return -1;
+ }
+ if (self->flags & OWNDATA) {
+ PyArray_XDECREF(self);
+ PyDataMem_FREE(self->data);
+ }
+ if (self->base) {
+ if (self->flags & UPDATEIFCOPY) {
+ ((PyArrayObject *)self->base)->flags |= WRITEABLE;
+ self->flags &= ~UPDATEIFCOPY;
+ }
+ Py_DECREF(self->base);
+ }
+ Py_INCREF(op);
+ self->base = op;
+ self->data = buf;
+ self->flags = CARRAY;
+ if (!writeable) {
+ self->flags &= ~WRITEABLE;
+ }
+ return 0;
+}
+
+
+static PyObject *
+array_itemsize_get(PyArrayObject *self)
+{
+ return PyInt_FromLong((long) self->descr->elsize);
+}
+
+static PyObject *
+array_size_get(PyArrayObject *self)
+{
+ intp size=PyArray_SIZE(self);
+#if SIZEOF_INTP <= SIZEOF_LONG
+ return PyInt_FromLong((long) size);
+#else
+ if (size > MAX_LONG || size < MIN_LONG) {
+ return PyLong_FromLongLong(size);
+ }
+ else {
+ return PyInt_FromLong((long) size);
+ }
+#endif
+}
+
+static PyObject *
+array_nbytes_get(PyArrayObject *self)
+{
+ intp nbytes = PyArray_NBYTES(self);
+#if SIZEOF_INTP <= SIZEOF_LONG
+ return PyInt_FromLong((long) nbytes);
+#else
+ if (nbytes > MAX_LONG || nbytes < MIN_LONG) {
+ return PyLong_FromLongLong(nbytes);
+ }
+ else {
+ return PyInt_FromLong((long) nbytes);
+ }
+#endif
+}
+
+
+/*
+ * If the type is changed.
+ * Also needing change: strides, itemsize
+ *
+ * Either itemsize is exactly the same or the array is single-segment
+ * (contiguous or fortran) with compatibile dimensions The shape and strides
+ * will be adjusted in that case as well.
+ */
+
+static int
+array_descr_set(PyArrayObject *self, PyObject *arg)
+{
+ PyArray_Descr *newtype = NULL;
+ intp newdim;
+ int index;
+ char *msg = "new type not compatible with array.";
+
+ if (!(PyArray_DescrConverter(arg, &newtype)) ||
+ newtype == NULL) {
+ PyErr_SetString(PyExc_TypeError, "invalid data-type for array");
+ return -1;
+ }
+ if (PyDataType_FLAGCHK(newtype, NPY_ITEM_HASOBJECT) ||
+ PyDataType_FLAGCHK(newtype, NPY_ITEM_IS_POINTER) ||
+ PyDataType_FLAGCHK(self->descr, NPY_ITEM_HASOBJECT) ||
+ PyDataType_FLAGCHK(self->descr, NPY_ITEM_IS_POINTER)) {
+ PyErr_SetString(PyExc_TypeError, \
+ "Cannot change data-type for object " \
+ "array.");
+ Py_DECREF(newtype);
+ return -1;
+ }
+
+ if (newtype->elsize == 0) {
+ PyErr_SetString(PyExc_TypeError,
+ "data-type must not be 0-sized");
+ Py_DECREF(newtype);
+ return -1;
+ }
+
+
+ if ((newtype->elsize != self->descr->elsize) &&
+ (self->nd == 0 || !PyArray_ISONESEGMENT(self) ||
+ newtype->subarray)) {
+ goto fail;
+ }
+ if (PyArray_ISCONTIGUOUS(self)) {
+ index = self->nd - 1;
+ }
+ else {
+ index = 0;
+ }
+ if (newtype->elsize < self->descr->elsize) {
+ /*
+ * if it is compatible increase the size of the
+ * dimension at end (or at the front for FORTRAN)
+ */
+ if (self->descr->elsize % newtype->elsize != 0) {
+ goto fail;
+ }
+ newdim = self->descr->elsize / newtype->elsize;
+ self->dimensions[index] *= newdim;
+ self->strides[index] = newtype->elsize;
+ }
+ else if (newtype->elsize > self->descr->elsize) {
+ /*
+ * Determine if last (or first if FORTRAN) dimension
+ * is compatible
+ */
+ newdim = self->dimensions[index] * self->descr->elsize;
+ if ((newdim % newtype->elsize) != 0) {
+ goto fail;
+ }
+ self->dimensions[index] = newdim / newtype->elsize;
+ self->strides[index] = newtype->elsize;
+ }
+
+ /* fall through -- adjust type*/
+ Py_DECREF(self->descr);
+ if (newtype->subarray) {
+ /*
+ * create new array object from data and update
+ * dimensions, strides and descr from it
+ */
+ PyArrayObject *temp;
+ /*
+ * We would decref newtype here.
+ * temp will steal a reference to it
+ */
+ temp = (PyArrayObject *)
+ PyArray_NewFromDescr(&PyArray_Type, newtype, self->nd,
+ self->dimensions, self->strides,
+ self->data, self->flags, NULL);
+ if (temp == NULL) {
+ return -1;
+ }
+ PyDimMem_FREE(self->dimensions);
+ self->dimensions = temp->dimensions;
+ self->nd = temp->nd;
+ self->strides = temp->strides;
+ newtype = temp->descr;
+ Py_INCREF(temp->descr);
+ /* Fool deallocator not to delete these*/
+ temp->nd = 0;
+ temp->dimensions = NULL;
+ Py_DECREF(temp);
+ }
+
+ self->descr = newtype;
+ PyArray_UpdateFlags(self, UPDATE_ALL);
+ return 0;
+
+ fail:
+ PyErr_SetString(PyExc_ValueError, msg);
+ Py_DECREF(newtype);
+ return -1;
+}
+
+static PyObject *
+array_struct_get(PyArrayObject *self)
+{
+ PyArrayInterface *inter;
+
+ inter = (PyArrayInterface *)_pya_malloc(sizeof(PyArrayInterface));
+ if (inter==NULL) {
+ return PyErr_NoMemory();
+ }
+ inter->two = 2;
+ inter->nd = self->nd;
+ inter->typekind = self->descr->kind;
+ inter->itemsize = self->descr->elsize;
+ inter->flags = self->flags;
+ /* reset unused flags */
+ inter->flags &= ~(UPDATEIFCOPY | OWNDATA);
+ if (PyArray_ISNOTSWAPPED(self)) inter->flags |= NOTSWAPPED;
+ /*
+ * Copy shape and strides over since these can be reset
+ *when the array is "reshaped".
+ */
+ if (self->nd > 0) {
+ inter->shape = (intp *)_pya_malloc(2*sizeof(intp)*self->nd);
+ if (inter->shape == NULL) {
+ _pya_free(inter);
+ return PyErr_NoMemory();
+ }
+ inter->strides = inter->shape + self->nd;
+ memcpy(inter->shape, self->dimensions, sizeof(intp)*self->nd);
+ memcpy(inter->strides, self->strides, sizeof(intp)*self->nd);
+ }
+ else {
+ inter->shape = NULL;
+ inter->strides = NULL;
+ }
+ inter->data = self->data;
+ if (self->descr->names) {
+ inter->descr = arraydescr_protocol_descr_get(self->descr);
+ if (inter->descr == NULL) {
+ PyErr_Clear();
+ }
+ else {
+ inter->flags &= ARR_HAS_DESCR;
+ }
+ }
+ else {
+ inter->descr = NULL;
+ }
+ Py_INCREF(self);
+ return PyCObject_FromVoidPtrAndDesc(inter, self, gentype_struct_free);
+}
+
+static PyObject *
+array_base_get(PyArrayObject *self)
+{
+ if (self->base == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ else {
+ Py_INCREF(self->base);
+ return self->base;
+ }
+}
+
+
+NPY_NO_EXPORT int
+_zerofill(PyArrayObject *ret)
+{
+ if (PyDataType_REFCHK(ret->descr)) {
+ PyObject *zero = PyInt_FromLong(0);
+ PyArray_FillObjectArray(ret, zero);
+ Py_DECREF(zero);
+ if (PyErr_Occurred()) {
+ Py_DECREF(ret);
+ return -1;
+ }
+ }
+ else {
+ intp n = PyArray_NBYTES(ret);
+ memset(ret->data, 0, n);
+ }
+ return 0;
+}
+
+
+/*
+ * Create a view of a complex array with an equivalent data-type
+ * except it is real instead of complex.
+ */
+static PyArrayObject *
+_get_part(PyArrayObject *self, int imag)
+{
+ PyArray_Descr *type;
+ PyArrayObject *ret;
+ int offset;
+
+ type = PyArray_DescrFromType(self->descr->type_num -
+ PyArray_NUM_FLOATTYPE);
+ offset = (imag ? type->elsize : 0);
+
+ if (!PyArray_ISNBO(self->descr->byteorder)) {
+ PyArray_Descr *new;
+ new = PyArray_DescrNew(type);
+ new->byteorder = self->descr->byteorder;
+ Py_DECREF(type);
+ type = new;
+ }
+ ret = (PyArrayObject *)
+ PyArray_NewFromDescr(self->ob_type,
+ type,
+ self->nd,
+ self->dimensions,
+ self->strides,
+ self->data + offset,
+ self->flags, (PyObject *)self);
+ if (ret == NULL) {
+ return NULL;
+ }
+ ret->flags &= ~CONTIGUOUS;
+ ret->flags &= ~FORTRAN;
+ Py_INCREF(self);
+ ret->base = (PyObject *)self;
+ return ret;
+}
+
+static PyObject *
+array_real_get(PyArrayObject *self)
+{
+ PyArrayObject *ret;
+
+ if (PyArray_ISCOMPLEX(self)) {
+ ret = _get_part(self, 0);
+ return (PyObject *)ret;
+ }
+ else {
+ Py_INCREF(self);
+ return (PyObject *)self;
+ }
+}
+
+
+static int
+array_real_set(PyArrayObject *self, PyObject *val)
+{
+ PyArrayObject *ret;
+ PyArrayObject *new;
+ int rint;
+
+ if (PyArray_ISCOMPLEX(self)) {
+ ret = _get_part(self, 0);
+ if (ret == NULL) {
+ return -1;
+ }
+ }
+ else {
+ Py_INCREF(self);
+ ret = self;
+ }
+ new = (PyArrayObject *)PyArray_FromAny(val, NULL, 0, 0, 0, NULL);
+ if (new == NULL) {
+ Py_DECREF(ret);
+ return -1;
+ }
+ rint = PyArray_MoveInto(ret, new);
+ Py_DECREF(ret);
+ Py_DECREF(new);
+ return rint;
+}
+
+static PyObject *
+array_imag_get(PyArrayObject *self)
+{
+ PyArrayObject *ret;
+
+ if (PyArray_ISCOMPLEX(self)) {
+ ret = _get_part(self, 1);
+ }
+ else {
+ Py_INCREF(self->descr);
+ ret = (PyArrayObject *)PyArray_NewFromDescr(self->ob_type,
+ self->descr,
+ self->nd,
+ self->dimensions,
+ NULL, NULL,
+ PyArray_ISFORTRAN(self),
+ (PyObject *)self);
+ if (ret == NULL) {
+ return NULL;
+ }
+ if (_zerofill(ret) < 0) {
+ return NULL;
+ }
+ ret->flags &= ~WRITEABLE;
+ }
+ return (PyObject *) ret;
+}
+
+static int
+array_imag_set(PyArrayObject *self, PyObject *val)
+{
+ if (PyArray_ISCOMPLEX(self)) {
+ PyArrayObject *ret;
+ PyArrayObject *new;
+ int rint;
+
+ ret = _get_part(self, 1);
+ if (ret == NULL) {
+ return -1;
+ }
+ new = (PyArrayObject *)PyArray_FromAny(val, NULL, 0, 0, 0, NULL);
+ if (new == NULL) {
+ Py_DECREF(ret);
+ return -1;
+ }
+ rint = PyArray_MoveInto(ret, new);
+ Py_DECREF(ret);
+ Py_DECREF(new);
+ return rint;
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "array does not have "\
+ "imaginary part to set");
+ return -1;
+ }
+}
+
+static PyObject *
+array_flat_get(PyArrayObject *self)
+{
+ return PyArray_IterNew((PyObject *)self);
+}
+
+static int
+array_flat_set(PyArrayObject *self, PyObject *val)
+{
+ PyObject *arr = NULL;
+ int retval = -1;
+ PyArrayIterObject *selfit = NULL, *arrit = NULL;
+ PyArray_Descr *typecode;
+ int swap;
+ PyArray_CopySwapFunc *copyswap;
+
+ typecode = self->descr;
+ Py_INCREF(typecode);
+ arr = PyArray_FromAny(val, typecode,
+ 0, 0, FORCECAST | FORTRAN_IF(self), NULL);
+ if (arr == NULL) {
+ return -1;
+ }
+ arrit = (PyArrayIterObject *)PyArray_IterNew(arr);
+ if (arrit == NULL) {
+ goto exit;
+ }
+ selfit = (PyArrayIterObject *)PyArray_IterNew((PyObject *)self);
+ if (selfit == NULL) {
+ goto exit;
+ }
+ if (arrit->size == 0) {
+ retval = 0;
+ goto exit;
+ }
+ swap = PyArray_ISNOTSWAPPED(self) != PyArray_ISNOTSWAPPED(arr);
+ copyswap = self->descr->f->copyswap;
+ if (PyDataType_REFCHK(self->descr)) {
+ while (selfit->index < selfit->size) {
+ PyArray_Item_XDECREF(selfit->dataptr, self->descr);
+ PyArray_Item_INCREF(arrit->dataptr, PyArray_DESCR(arr));
+ memmove(selfit->dataptr, arrit->dataptr, sizeof(PyObject **));
+ if (swap) {
+ copyswap(selfit->dataptr, NULL, swap, self);
+ }
+ PyArray_ITER_NEXT(selfit);
+ PyArray_ITER_NEXT(arrit);
+ if (arrit->index == arrit->size) {
+ PyArray_ITER_RESET(arrit);
+ }
+ }
+ retval = 0;
+ goto exit;
+ }
+
+ while(selfit->index < selfit->size) {
+ memmove(selfit->dataptr, arrit->dataptr, self->descr->elsize);
+ if (swap) {
+ copyswap(selfit->dataptr, NULL, swap, self);
+ }
+ PyArray_ITER_NEXT(selfit);
+ PyArray_ITER_NEXT(arrit);
+ if (arrit->index == arrit->size) {
+ PyArray_ITER_RESET(arrit);
+ }
+ }
+ retval = 0;
+
+ exit:
+ Py_XDECREF(selfit);
+ Py_XDECREF(arrit);
+ Py_XDECREF(arr);
+ return retval;
+}
+
+static PyObject *
+array_transpose_get(PyArrayObject *self)
+{
+ return PyArray_Transpose(self, NULL);
+}
+
+/* If this is None, no function call is made
+ --- default sub-class behavior
+*/
+static PyObject *
+array_finalize_get(PyArrayObject *NPY_UNUSED(self))
+{
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+NPY_NO_EXPORT PyGetSetDef array_getsetlist[] = {
+ {"ndim",
+ (getter)array_ndim_get,
+ NULL, NULL, NULL},
+ {"flags",
+ (getter)array_flags_get,
+ NULL, NULL, NULL},
+ {"shape",
+ (getter)array_shape_get,
+ (setter)array_shape_set,
+ NULL, NULL},
+ {"strides",
+ (getter)array_strides_get,
+ (setter)array_strides_set,
+ NULL, NULL},
+ {"data",
+ (getter)array_data_get,
+ (setter)array_data_set,
+ NULL, NULL},
+ {"itemsize",
+ (getter)array_itemsize_get,
+ NULL, NULL, NULL},
+ {"size",
+ (getter)array_size_get,
+ NULL, NULL, NULL},
+ {"nbytes",
+ (getter)array_nbytes_get,
+ NULL, NULL, NULL},
+ {"base",
+ (getter)array_base_get,
+ NULL, NULL, NULL},
+ {"dtype",
+ (getter)array_descr_get,
+ (setter)array_descr_set,
+ NULL, NULL},
+ {"real",
+ (getter)array_real_get,
+ (setter)array_real_set,
+ NULL, NULL},
+ {"imag",
+ (getter)array_imag_get,
+ (setter)array_imag_set,
+ NULL, NULL},
+ {"flat",
+ (getter)array_flat_get,
+ (setter)array_flat_set,
+ NULL, NULL},
+ {"ctypes",
+ (getter)array_ctypes_get,
+ NULL, NULL, NULL},
+ {"T",
+ (getter)array_transpose_get,
+ NULL, NULL, NULL},
+ {"__array_interface__",
+ (getter)array_interface_get,
+ NULL, NULL, NULL},
+ {"__array_struct__",
+ (getter)array_struct_get,
+ NULL, NULL, NULL},
+ {"__array_priority__",
+ (getter)array_priority_get,
+ NULL, NULL, NULL},
+ {"__array_finalize__",
+ (getter)array_finalize_get,
+ NULL, NULL, NULL},
+ {NULL, NULL, NULL, NULL, NULL}, /* Sentinel */
+};
+
+/****************** end of attribute get and set routines *******************/