summaryrefslogtreecommitdiff
path: root/numpy/core/src/arrayobject.c
diff options
context:
space:
mode:
authorDavid Cournapeau <cournape@gmail.com>2009-04-30 08:36:36 +0000
committerDavid Cournapeau <cournape@gmail.com>2009-04-30 08:36:36 +0000
commitefd5b424216fb0ce6aa3c7529d8c3e1d5ae34116 (patch)
treef2a4e44ebcdaf4a90fb59c1f0c392728d9846239 /numpy/core/src/arrayobject.c
parentfe1f93464b6115ad441bd328ca87f78f2852de49 (diff)
downloadnumpy-efd5b424216fb0ce6aa3c7529d8c3e1d5ae34116.tar.gz
Put mapping protocol in separate file.
Diffstat (limited to 'numpy/core/src/arrayobject.c')
-rw-r--r--numpy/core/src/arrayobject.c996
1 files changed, 1 insertions, 995 deletions
diff --git a/numpy/core/src/arrayobject.c b/numpy/core/src/arrayobject.c
index e8d6dc541..1d9256b28 100644
--- a/numpy/core/src/arrayobject.c
+++ b/numpy/core/src/arrayobject.c
@@ -33,6 +33,7 @@ maintainer email: oliphant.travis@ieee.org
#include "arrayobject.h"
#include "arraydescr.h"
#include "arrayiterators.h"
+#include "arraymapping.h"
#ifndef Py_UNICODE_WIDE
#include "ucsnarrow.h"
#endif
@@ -2145,1001 +2146,6 @@ array_dealloc(PyArrayObject *self) {
}
/*************************************************************************
- **************** Implement Mapping Protocol ***************************
- *************************************************************************/
-
-static Py_ssize_t
-array_length(PyArrayObject *self)
-{
- if (self->nd != 0) {
- return self->dimensions[0];
- } else {
- PyErr_SetString(PyExc_TypeError, "len() of unsized object");
- return -1;
- }
-}
-
-NPY_NO_EXPORT PyObject *
-array_big_item(PyArrayObject *self, intp i)
-{
- char *item;
- PyArrayObject *r;
-
- if(self->nd == 0) {
- PyErr_SetString(PyExc_IndexError,
- "0-d arrays can't be indexed");
- return NULL;
- }
- if ((item = index2ptr(self, i)) == NULL) {
- return NULL;
- }
- Py_INCREF(self->descr);
- r = (PyArrayObject *)PyArray_NewFromDescr(self->ob_type,
- self->descr,
- self->nd-1,
- self->dimensions+1,
- self->strides+1, item,
- self->flags,
- (PyObject *)self);
- if (r == NULL) {
- return NULL;
- }
- Py_INCREF(self);
- r->base = (PyObject *)self;
- PyArray_UpdateFlags(r, CONTIGUOUS | FORTRAN);
- return (PyObject *)r;
-}
-
-/* contains optimization for 1-d arrays */
-static PyObject *
-array_item_nice(PyArrayObject *self, Py_ssize_t i)
-{
- if (self->nd == 1) {
- char *item;
- if ((item = index2ptr(self, i)) == NULL) {
- return NULL;
- }
- return PyArray_Scalar(item, self->descr, (PyObject *)self);
- }
- else {
- return PyArray_Return(
- (PyArrayObject *) array_big_item(self, (intp) i));
- }
-}
-
-static int
-array_ass_big_item(PyArrayObject *self, intp i, PyObject *v)
-{
- PyArrayObject *tmp;
- char *item;
- int ret;
-
- if (v == NULL) {
- PyErr_SetString(PyExc_ValueError,
- "can't delete array elements");
- return -1;
- }
- if (!PyArray_ISWRITEABLE(self)) {
- PyErr_SetString(PyExc_RuntimeError,
- "array is not writeable");
- return -1;
- }
- if (self->nd == 0) {
- PyErr_SetString(PyExc_IndexError,
- "0-d arrays can't be indexed.");
- return -1;
- }
-
-
- if (self->nd > 1) {
- if((tmp = (PyArrayObject *)array_big_item(self, i)) == NULL) {
- return -1;
- }
- ret = PyArray_CopyObject(tmp, v);
- Py_DECREF(tmp);
- return ret;
- }
-
- if ((item = index2ptr(self, i)) == NULL) {
- return -1;
- }
- if (self->descr->f->setitem(v, item, self) == -1) {
- return -1;
- }
- return 0;
-}
-
-#if PY_VERSION_HEX < 0x02050000
-#if SIZEOF_INT == SIZEOF_INTP
-#define array_ass_item array_ass_big_item
-#endif
-#else
-#if SIZEOF_SIZE_T == SIZEOF_INTP
-#define array_ass_item array_ass_big_item
-#endif
-#endif
-#ifndef array_ass_item
-static int
-array_ass_item(PyArrayObject *self, Py_ssize_t i, PyObject *v)
-{
- return array_ass_big_item(self, (intp) i, v);
-}
-#endif
-
-
-/* -------------------------------------------------------------- */
-
-static void
-_swap_axes(PyArrayMapIterObject *mit, PyArrayObject **ret, int getmap)
-{
- PyObject *new;
- int n1, n2, n3, val, bnd;
- int i;
- PyArray_Dims permute;
- intp d[MAX_DIMS];
- PyArrayObject *arr;
-
- permute.ptr = d;
- permute.len = mit->nd;
-
- /*
- * arr might not have the right number of dimensions
- * and need to be reshaped first by pre-pending ones
- */
- arr = *ret;
- if (arr->nd != mit->nd) {
- for (i = 1; i <= arr->nd; i++) {
- permute.ptr[mit->nd-i] = arr->dimensions[arr->nd-i];
- }
- for (i = 0; i < mit->nd-arr->nd; i++) {
- permute.ptr[i] = 1;
- }
- new = PyArray_Newshape(arr, &permute, PyArray_ANYORDER);
- Py_DECREF(arr);
- *ret = (PyArrayObject *)new;
- if (new == NULL) {
- return;
- }
- }
-
- /*
- * Setting and getting need to have different permutations.
- * On the get we are permuting the returned object, but on
- * setting we are permuting the object-to-be-set.
- * The set permutation is the inverse of the get permutation.
- */
-
- /*
- * For getting the array the tuple for transpose is
- * (n1,...,n1+n2-1,0,...,n1-1,n1+n2,...,n3-1)
- * n1 is the number of dimensions of the broadcast index array
- * n2 is the number of dimensions skipped at the start
- * n3 is the number of dimensions of the result
- */
-
- /*
- * For setting the array the tuple for transpose is
- * (n2,...,n1+n2-1,0,...,n2-1,n1+n2,...n3-1)
- */
- n1 = mit->iters[0]->nd_m1 + 1;
- n2 = mit->iteraxes[0];
- n3 = mit->nd;
-
- /* use n1 as the boundary if getting but n2 if setting */
- bnd = getmap ? n1 : n2;
- val = bnd;
- i = 0;
- while (val < n1 + n2) {
- permute.ptr[i++] = val++;
- }
- val = 0;
- while (val < bnd) {
- permute.ptr[i++] = val++;
- }
- val = n1 + n2;
- while (val < n3) {
- permute.ptr[i++] = val++;
- }
- new = PyArray_Transpose(*ret, &permute);
- Py_DECREF(*ret);
- *ret = (PyArrayObject *)new;
-}
-
-static PyObject *
-PyArray_GetMap(PyArrayMapIterObject *mit)
-{
-
- PyArrayObject *ret, *temp;
- PyArrayIterObject *it;
- int index;
- int swap;
- PyArray_CopySwapFunc *copyswap;
-
- /* Unbound map iterator --- Bind should have been called */
- if (mit->ait == NULL) {
- return NULL;
- }
-
- /* This relies on the map iterator object telling us the shape
- of the new array in nd and dimensions.
- */
- temp = mit->ait->ao;
- Py_INCREF(temp->descr);
- ret = (PyArrayObject *)
- PyArray_NewFromDescr(temp->ob_type,
- temp->descr,
- mit->nd, mit->dimensions,
- NULL, NULL,
- PyArray_ISFORTRAN(temp),
- (PyObject *)temp);
- if (ret == NULL) {
- return NULL;
- }
-
- /*
- * Now just iterate through the new array filling it in
- * with the next object from the original array as
- * defined by the mapping iterator
- */
-
- if ((it = (PyArrayIterObject *)PyArray_IterNew((PyObject *)ret)) == NULL) {
- Py_DECREF(ret);
- return NULL;
- }
- index = it->size;
- swap = (PyArray_ISNOTSWAPPED(temp) != PyArray_ISNOTSWAPPED(ret));
- copyswap = ret->descr->f->copyswap;
- PyArray_MapIterReset(mit);
- while (index--) {
- copyswap(it->dataptr, mit->dataptr, swap, ret);
- PyArray_MapIterNext(mit);
- PyArray_ITER_NEXT(it);
- }
- Py_DECREF(it);
-
- /* check for consecutive axes */
- if ((mit->subspace != NULL) && (mit->consec)) {
- if (mit->iteraxes[0] > 0) { /* then we need to swap */
- _swap_axes(mit, &ret, 1);
- }
- }
- return (PyObject *)ret;
-}
-
-static int
-PyArray_SetMap(PyArrayMapIterObject *mit, PyObject *op)
-{
- PyObject *arr = NULL;
- PyArrayIterObject *it;
- int index;
- int swap;
- PyArray_CopySwapFunc *copyswap;
- PyArray_Descr *descr;
-
- /* Unbound Map Iterator */
- if (mit->ait == NULL) {
- return -1;
- }
- descr = mit->ait->ao->descr;
- Py_INCREF(descr);
- arr = PyArray_FromAny(op, descr, 0, 0, FORCECAST, NULL);
- if (arr == NULL) {
- return -1;
- }
- if ((mit->subspace != NULL) && (mit->consec)) {
- if (mit->iteraxes[0] > 0) { /* then we need to swap */
- _swap_axes(mit, (PyArrayObject **)&arr, 0);
- if (arr == NULL) {
- return -1;
- }
- }
- }
-
- /* Be sure values array is "broadcastable"
- to shape of mit->dimensions, mit->nd */
-
- if ((it = (PyArrayIterObject *)\
- PyArray_BroadcastToShape(arr, mit->dimensions, mit->nd))==NULL) {
- Py_DECREF(arr);
- return -1;
- }
-
- index = mit->size;
- swap = (PyArray_ISNOTSWAPPED(mit->ait->ao) !=
- (PyArray_ISNOTSWAPPED(arr)));
- copyswap = PyArray_DESCR(arr)->f->copyswap;
- PyArray_MapIterReset(mit);
- /* Need to decref hasobject arrays */
- if (PyDataType_FLAGCHK(descr, NPY_ITEM_REFCOUNT)) {
- while (index--) {
- PyArray_Item_XDECREF(mit->dataptr, PyArray_DESCR(arr));
- PyArray_Item_INCREF(it->dataptr, PyArray_DESCR(arr));
- memmove(mit->dataptr, it->dataptr, sizeof(PyObject *));
- /* ignored unless VOID array with object's */
- if (swap) {
- copyswap(mit->dataptr, NULL, swap, arr);
- }
- PyArray_MapIterNext(mit);
- PyArray_ITER_NEXT(it);
- }
- Py_DECREF(arr);
- Py_DECREF(it);
- return 0;
- }
- while(index--) {
- memmove(mit->dataptr, it->dataptr, PyArray_ITEMSIZE(arr));
- if (swap) {
- copyswap(mit->dataptr, NULL, swap, arr);
- }
- PyArray_MapIterNext(mit);
- PyArray_ITER_NEXT(it);
- }
- Py_DECREF(arr);
- Py_DECREF(it);
- return 0;
-}
-
-NPY_NO_EXPORT int
-count_new_axes_0d(PyObject *tuple)
-{
- int i, argument_count;
- int ellipsis_count = 0;
- int newaxis_count = 0;
-
- argument_count = PyTuple_GET_SIZE(tuple);
- for (i = 0; i < argument_count; ++i) {
- PyObject *arg = PyTuple_GET_ITEM(tuple, i);
- if (arg == Py_Ellipsis && !ellipsis_count) {
- ellipsis_count++;
- }
- else if (arg == Py_None) {
- newaxis_count++;
- }
- else {
- break;
- }
- }
- if (i < argument_count) {
- PyErr_SetString(PyExc_IndexError,
- "0-d arrays can only use a single ()"
- " or a list of newaxes (and a single ...)"
- " as an index");
- return -1;
- }
- if (newaxis_count > MAX_DIMS) {
- PyErr_SetString(PyExc_IndexError, "too many dimensions");
- return -1;
- }
- return newaxis_count;
-}
-
-NPY_NO_EXPORT PyObject *
-add_new_axes_0d(PyArrayObject *arr, int newaxis_count)
-{
- PyArrayObject *other;
- intp dimensions[MAX_DIMS];
- int i;
-
- for (i = 0; i < newaxis_count; ++i) {
- dimensions[i] = 1;
- }
- Py_INCREF(arr->descr);
- if ((other = (PyArrayObject *)
- PyArray_NewFromDescr(arr->ob_type, arr->descr,
- newaxis_count, dimensions,
- NULL, arr->data,
- arr->flags,
- (PyObject *)arr)) == NULL)
- return NULL;
- other->base = (PyObject *)arr;
- Py_INCREF(arr);
- return (PyObject *)other;
-}
-
-
-/* This checks the args for any fancy indexing objects */
-
-static int
-fancy_indexing_check(PyObject *args)
-{
- int i, n;
- PyObject *obj;
- int retval = SOBJ_NOTFANCY;
-
- if (PyTuple_Check(args)) {
- n = PyTuple_GET_SIZE(args);
- if (n >= MAX_DIMS) {
- return SOBJ_TOOMANY;
- }
- for (i = 0; i < n; i++) {
- obj = PyTuple_GET_ITEM(args,i);
- if (PyArray_Check(obj)) {
- if (PyArray_ISINTEGER(obj) ||
- PyArray_ISBOOL(obj)) {
- retval = SOBJ_ISFANCY;
- }
- else {
- retval = SOBJ_BADARRAY;
- break;
- }
- }
- else if (PySequence_Check(obj)) {
- retval = SOBJ_ISFANCY;
- }
- }
- }
- else if (PyArray_Check(args)) {
- if ((PyArray_TYPE(args)==PyArray_BOOL) ||
- (PyArray_ISINTEGER(args))) {
- return SOBJ_ISFANCY;
- }
- else {
- return SOBJ_BADARRAY;
- }
- }
- else if (PySequence_Check(args)) {
- /*
- * Sequences < MAX_DIMS with any slice objects
- * or newaxis, or Ellipsis is considered standard
- * as long as there are also no Arrays and or additional
- * sequences embedded.
- */
- retval = SOBJ_ISFANCY;
- n = PySequence_Size(args);
- if (n < 0 || n >= MAX_DIMS) {
- return SOBJ_ISFANCY;
- }
- for (i = 0; i < n; i++) {
- obj = PySequence_GetItem(args, i);
- if (obj == NULL) {
- return SOBJ_ISFANCY;
- }
- if (PyArray_Check(obj)) {
- if (PyArray_ISINTEGER(obj) || PyArray_ISBOOL(obj)) {
- retval = SOBJ_LISTTUP;
- }
- else {
- retval = SOBJ_BADARRAY;
- }
- }
- else if (PySequence_Check(obj)) {
- retval = SOBJ_LISTTUP;
- }
- else if (PySlice_Check(obj) || obj == Py_Ellipsis ||
- obj == Py_None) {
- retval = SOBJ_NOTFANCY;
- }
- Py_DECREF(obj);
- if (retval > SOBJ_ISFANCY) {
- return retval;
- }
- }
- }
- return retval;
-}
-
-/*
- * Called when treating array object like a mapping -- called first from
- * Python when using a[object] unless object is a standard slice object
- * (not an extended one).
- *
- * There are two situations:
- *
- * 1 - the subscript is a standard view and a reference to the
- * array can be returned
- *
- * 2 - the subscript uses Boolean masks or integer indexing and
- * therefore a new array is created and returned.
- */
-
-NPY_NO_EXPORT PyObject *
-array_subscript_simple(PyArrayObject *self, PyObject *op)
-{
- intp dimensions[MAX_DIMS], strides[MAX_DIMS];
- intp offset;
- int nd;
- PyArrayObject *other;
- intp value;
-
- value = PyArray_PyIntAsIntp(op);
- if (!PyErr_Occurred()) {
- return array_big_item(self, value);
- }
- PyErr_Clear();
-
- /* Standard (view-based) Indexing */
- if ((nd = parse_index(self, op, dimensions, strides, &offset)) == -1) {
- return NULL;
- }
- /* This will only work if new array will be a view */
- Py_INCREF(self->descr);
- if ((other = (PyArrayObject *)
- PyArray_NewFromDescr(self->ob_type, self->descr,
- nd, dimensions,
- strides, self->data+offset,
- self->flags,
- (PyObject *)self)) == NULL) {
- return NULL;
- }
- other->base = (PyObject *)self;
- Py_INCREF(self);
- PyArray_UpdateFlags(other, UPDATE_ALL);
- return (PyObject *)other;
-}
-
-static PyObject *
-array_subscript(PyArrayObject *self, PyObject *op)
-{
- int nd, fancy;
- PyArrayObject *other;
- PyArrayMapIterObject *mit;
- PyObject *obj;
-
- if (PyString_Check(op) || PyUnicode_Check(op)) {
- if (self->descr->names) {
- obj = PyDict_GetItem(self->descr->fields, op);
- if (obj != NULL) {
- PyArray_Descr *descr;
- int offset;
- PyObject *title;
-
- if (PyArg_ParseTuple(obj, "Oi|O", &descr, &offset, &title)) {
- Py_INCREF(descr);
- return PyArray_GetField(self, descr, offset);
- }
- }
- }
-
- PyErr_Format(PyExc_ValueError,
- "field named %s not found.",
- PyString_AsString(op));
- return NULL;
- }
-
- /* Check for multiple field access */
- if (self->descr->names && PySequence_Check(op) && !PyTuple_Check(op)) {
- int seqlen, i;
- seqlen = PySequence_Size(op);
- for (i = 0; i < seqlen; i++) {
- obj = PySequence_GetItem(op, i);
- if (!PyString_Check(obj) && !PyUnicode_Check(obj)) {
- Py_DECREF(obj);
- break;
- }
- Py_DECREF(obj);
- }
- /*
- * extract multiple fields if all elements in sequence
- * are either string or unicode (i.e. no break occurred).
- */
- fancy = ((seqlen > 0) && (i == seqlen));
- if (fancy) {
- PyObject *_numpy_internal;
- _numpy_internal = PyImport_ImportModule("numpy.core._internal");
- if (_numpy_internal == NULL) {
- return NULL;
- }
- obj = PyObject_CallMethod(_numpy_internal,
- "_index_fields", "OO", self, op);
- Py_DECREF(_numpy_internal);
- return obj;
- }
- }
-
- if (op == Py_Ellipsis) {
- Py_INCREF(self);
- return (PyObject *)self;
- }
-
- if (self->nd == 0) {
- if (op == Py_None) {
- return add_new_axes_0d(self, 1);
- }
- if (PyTuple_Check(op)) {
- if (0 == PyTuple_GET_SIZE(op)) {
- Py_INCREF(self);
- return (PyObject *)self;
- }
- if ((nd = count_new_axes_0d(op)) == -1) {
- return NULL;
- }
- return add_new_axes_0d(self, nd);
- }
- /* Allow Boolean mask selection also */
- if ((PyArray_Check(op) && (PyArray_DIMS(op)==0)
- && PyArray_ISBOOL(op))) {
- if (PyObject_IsTrue(op)) {
- Py_INCREF(self);
- return (PyObject *)self;
- }
- else {
- intp oned = 0;
- Py_INCREF(self->descr);
- return PyArray_NewFromDescr(self->ob_type,
- self->descr,
- 1, &oned,
- NULL, NULL,
- NPY_DEFAULT,
- NULL);
- }
- }
- PyErr_SetString(PyExc_IndexError, "0-d arrays can't be indexed.");
- return NULL;
- }
-
- fancy = fancy_indexing_check(op);
- if (fancy != SOBJ_NOTFANCY) {
- int oned;
-
- oned = ((self->nd == 1) &&
- !(PyTuple_Check(op) && PyTuple_GET_SIZE(op) > 1));
-
- /* wrap arguments into a mapiter object */
- mit = (PyArrayMapIterObject *) PyArray_MapIterNew(op, oned, fancy);
- if (mit == NULL) {
- return NULL;
- }
- if (oned) {
- PyArrayIterObject *it;
- PyObject *rval;
- it = (PyArrayIterObject *) PyArray_IterNew((PyObject *)self);
- if (it == NULL) {
- Py_DECREF(mit);
- return NULL;
- }
- rval = iter_subscript(it, mit->indexobj);
- Py_DECREF(it);
- Py_DECREF(mit);
- return rval;
- }
- PyArray_MapIterBind(mit, self);
- other = (PyArrayObject *)PyArray_GetMap(mit);
- Py_DECREF(mit);
- return (PyObject *)other;
- }
-
- return array_subscript_simple(self, op);
-}
-
-
-/*
- * Another assignment hacked by using CopyObject.
- * This only works if subscript returns a standard view.
- * Again there are two cases. In the first case, PyArray_CopyObject
- * can be used. In the second case, a new indexing function has to be
- * used.
- */
-
-static int
-array_ass_sub_simple(PyArrayObject *self, PyObject *index, PyObject *op)
-{
- int ret;
- PyArrayObject *tmp;
- intp value;
-
- value = PyArray_PyIntAsIntp(index);
- if (!error_converting(value)) {
- return array_ass_big_item(self, value, op);
- }
- PyErr_Clear();
-
- /* Rest of standard (view-based) indexing */
-
- if (PyArray_CheckExact(self)) {
- tmp = (PyArrayObject *)array_subscript_simple(self, index);
- if (tmp == NULL) {
- return -1;
- }
- }
- else {
- PyObject *tmp0;
- tmp0 = PyObject_GetItem((PyObject *)self, index);
- if (tmp0 == NULL) {
- return -1;
- }
- if (!PyArray_Check(tmp0)) {
- PyErr_SetString(PyExc_RuntimeError,
- "Getitem not returning array.");
- Py_DECREF(tmp0);
- return -1;
- }
- tmp = (PyArrayObject *)tmp0;
- }
-
- if (PyArray_ISOBJECT(self) && (tmp->nd == 0)) {
- ret = tmp->descr->f->setitem(op, tmp->data, tmp);
- }
- else {
- ret = PyArray_CopyObject(tmp, op);
- }
- Py_DECREF(tmp);
- return ret;
-}
-
-
-/* return -1 if tuple-object seq is not a tuple of integers.
- otherwise fill vals with converted integers
-*/
-static int
-_tuple_of_integers(PyObject *seq, intp *vals, int maxvals)
-{
- int i;
- PyObject *obj;
- intp temp;
-
- for(i=0; i<maxvals; i++) {
- obj = PyTuple_GET_ITEM(seq, i);
- if ((PyArray_Check(obj) && PyArray_NDIM(obj) > 0)
- || PyList_Check(obj)) {
- return -1;
- }
- temp = PyArray_PyIntAsIntp(obj);
- if (error_converting(temp)) {
- return -1;
- }
- vals[i] = temp;
- }
- return 0;
-}
-
-
-static int
-array_ass_sub(PyArrayObject *self, PyObject *index, PyObject *op)
-{
- int ret, oned, fancy;
- PyArrayMapIterObject *mit;
- intp vals[MAX_DIMS];
-
- if (op == NULL) {
- PyErr_SetString(PyExc_ValueError,
- "cannot delete array elements");
- return -1;
- }
- if (!PyArray_ISWRITEABLE(self)) {
- PyErr_SetString(PyExc_RuntimeError,
- "array is not writeable");
- return -1;
- }
-
- if (PyInt_Check(index) || PyArray_IsScalar(index, Integer) ||
- PyLong_Check(index) || (PyIndex_Check(index) &&
- !PySequence_Check(index))) {
- intp value;
- value = PyArray_PyIntAsIntp(index);
- if (PyErr_Occurred()) {
- PyErr_Clear();
- }
- else {
- return array_ass_big_item(self, value, op);
- }
- }
-
- if (PyString_Check(index) || PyUnicode_Check(index)) {
- if (self->descr->names) {
- PyObject *obj;
-
- obj = PyDict_GetItem(self->descr->fields, index);
- if (obj != NULL) {
- PyArray_Descr *descr;
- int offset;
- PyObject *title;
-
- if (PyArg_ParseTuple(obj, "Oi|O", &descr, &offset, &title)) {
- Py_INCREF(descr);
- return PyArray_SetField(self, descr, offset, op);
- }
- }
- }
-
- PyErr_Format(PyExc_ValueError,
- "field named %s not found.",
- PyString_AsString(index));
- return -1;
- }
-
- if (self->nd == 0) {
- /*
- * Several different exceptions to the 0-d no-indexing rule
- *
- * 1) ellipses
- * 2) empty tuple
- * 3) Using newaxis (None)
- * 4) Boolean mask indexing
- */
- if (index == Py_Ellipsis || index == Py_None ||
- (PyTuple_Check(index) && (0 == PyTuple_GET_SIZE(index) ||
- count_new_axes_0d(index) > 0))) {
- return self->descr->f->setitem(op, self->data, self);
- }
- if (PyBool_Check(index) || PyArray_IsScalar(index, Bool) ||
- (PyArray_Check(index) && (PyArray_DIMS(index)==0) &&
- PyArray_ISBOOL(index))) {
- if (PyObject_IsTrue(index)) {
- return self->descr->f->setitem(op, self->data, self);
- }
- else { /* don't do anything */
- return 0;
- }
- }
- PyErr_SetString(PyExc_IndexError, "0-d arrays can't be indexed.");
- return -1;
- }
-
- /* optimization for integer-tuple */
- if (self->nd > 1 &&
- (PyTuple_Check(index) && (PyTuple_GET_SIZE(index) == self->nd))
- && (_tuple_of_integers(index, vals, self->nd) >= 0)) {
- int i;
- char *item;
-
- for (i = 0; i < self->nd; i++) {
- if (vals[i] < 0) {
- vals[i] += self->dimensions[i];
- }
- if ((vals[i] < 0) || (vals[i] >= self->dimensions[i])) {
- PyErr_Format(PyExc_IndexError,
- "index (%"INTP_FMT") out of range "\
- "(0<=index<%"INTP_FMT") in dimension %d",
- vals[i], self->dimensions[i], i);
- return -1;
- }
- }
- item = PyArray_GetPtr(self, vals);
- return self->descr->f->setitem(op, item, self);
- }
- PyErr_Clear();
-
- fancy = fancy_indexing_check(index);
- if (fancy != SOBJ_NOTFANCY) {
- oned = ((self->nd == 1) &&
- !(PyTuple_Check(index) && PyTuple_GET_SIZE(index) > 1));
- mit = (PyArrayMapIterObject *) PyArray_MapIterNew(index, oned, fancy);
- if (mit == NULL) {
- return -1;
- }
- if (oned) {
- PyArrayIterObject *it;
- int rval;
-
- it = (PyArrayIterObject *)PyArray_IterNew((PyObject *)self);
- if (it == NULL) {
- Py_DECREF(mit);
- return -1;
- }
- rval = iter_ass_subscript(it, mit->indexobj, op);
- Py_DECREF(it);
- Py_DECREF(mit);
- return rval;
- }
- PyArray_MapIterBind(mit, self);
- ret = PyArray_SetMap(mit, op);
- Py_DECREF(mit);
- return ret;
- }
-
- return array_ass_sub_simple(self, index, op);
-}
-
-
-/*
- * There are places that require that array_subscript return a PyArrayObject
- * and not possibly a scalar. Thus, this is the function exposed to
- * Python so that 0-dim arrays are passed as scalars
- */
-
-
-static PyObject *
-array_subscript_nice(PyArrayObject *self, PyObject *op)
-{
-
- PyArrayObject *mp;
- intp vals[MAX_DIMS];
-
- if (PyInt_Check(op) || PyArray_IsScalar(op, Integer) ||
- PyLong_Check(op) || (PyIndex_Check(op) &&
- !PySequence_Check(op))) {
- intp value;
- value = PyArray_PyIntAsIntp(op);
- if (PyErr_Occurred()) {
- PyErr_Clear();
- }
- else {
- return array_item_nice(self, (Py_ssize_t) value);
- }
- }
- /* optimization for a tuple of integers */
- if (self->nd > 1 && PyTuple_Check(op) &&
- (PyTuple_GET_SIZE(op) == self->nd)
- && (_tuple_of_integers(op, vals, self->nd) >= 0)) {
- int i;
- char *item;
-
- for (i = 0; i < self->nd; i++) {
- if (vals[i] < 0) {
- vals[i] += self->dimensions[i];
- }
- if ((vals[i] < 0) || (vals[i] >= self->dimensions[i])) {
- PyErr_Format(PyExc_IndexError,
- "index (%"INTP_FMT") out of range "\
- "(0<=index<%"INTP_FMT") in dimension %d",
- vals[i], self->dimensions[i], i);
- return NULL;
- }
- }
- item = PyArray_GetPtr(self, vals);
- return PyArray_Scalar(item, self->descr, (PyObject *)self);
- }
- PyErr_Clear();
-
- mp = (PyArrayObject *)array_subscript(self, op);
- /*
- * mp could be a scalar if op is not an Int, Scalar, Long or other Index
- * object and still convertable to an integer (so that the code goes to
- * array_subscript_simple). So, this cast is a bit dangerous..
- */
-
- /*
- * The following is just a copy of PyArray_Return with an
- * additional logic in the nd == 0 case.
- */
-
- if (mp == NULL) {
- return NULL;
- }
- if (PyErr_Occurred()) {
- Py_XDECREF(mp);
- return NULL;
- }
- if (PyArray_Check(mp) && mp->nd == 0) {
- Bool noellipses = TRUE;
- if ((op == Py_Ellipsis) || PyString_Check(op) || PyUnicode_Check(op)) {
- noellipses = FALSE;
- }
- else if (PyBool_Check(op) || PyArray_IsScalar(op, Bool) ||
- (PyArray_Check(op) && (PyArray_DIMS(op)==0) &&
- PyArray_ISBOOL(op))) {
- noellipses = FALSE;
- }
- else if (PySequence_Check(op)) {
- Py_ssize_t n, i;
- PyObject *temp;
-
- n = PySequence_Size(op);
- i = 0;
- while (i < n && noellipses) {
- temp = PySequence_GetItem(op, i);
- if (temp == Py_Ellipsis) {
- noellipses = FALSE;
- }
- Py_DECREF(temp);
- i++;
- }
- }
- if (noellipses) {
- PyObject *ret;
- ret = PyArray_ToScalar(mp->data, mp);
- Py_DECREF(mp);
- return ret;
- }
- }
- return (PyObject *)mp;
-}
-
-
-static PyMappingMethods array_as_mapping = {
-#if PY_VERSION_HEX >= 0x02050000
- (lenfunc)array_length, /*mp_length*/
-#else
- (inquiry)array_length, /*mp_length*/
-#endif
- (binaryfunc)array_subscript_nice, /*mp_subscript*/
- (objobjargproc)array_ass_sub, /*mp_ass_subscript*/
-};
-
-/****************** End of Mapping Protocol ******************************/
-
-
-/*************************************************************************
**************** Implement Buffer Protocol ****************************
*************************************************************************/