summaryrefslogtreecommitdiff
path: root/numpy/core/src/arrayobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/core/src/arrayobject.c')
-rw-r--r--numpy/core/src/arrayobject.c3265
1 files changed, 0 insertions, 3265 deletions
diff --git a/numpy/core/src/arrayobject.c b/numpy/core/src/arrayobject.c
deleted file mode 100644
index 076547a8c..000000000
--- a/numpy/core/src/arrayobject.c
+++ /dev/null
@@ -1,3265 +0,0 @@
-/*
- Provide multidimensional arrays as a basic object type in python.
-
- Based on Original Numeric implementation
- Copyright (c) 1995, 1996, 1997 Jim Hugunin, hugunin@mit.edu
-
- with contributions from many Numeric Python developers 1995-2004
-
- Heavily modified in 2005 with inspiration from Numarray
-
- by
-
- Travis Oliphant, oliphant@ee.byu.edu
- Brigham Young Univeristy
-
-
-maintainer email: oliphant.travis@ieee.org
-
- Numarray design (which provided guidance) by
- Space Science Telescope Institute
- (J. Todd Miller, Perry Greenfield, Rick White)
-*/
-#define PY_SSIZE_T_CLEAN
-#include <Python.h>
-#include "structmember.h"
-
-/*#include <stdio.h>*/
-#define _MULTIARRAYMODULE
-#define NPY_NO_PREFIX
-#include "numpy/arrayobject.h"
-#include "numpy/arrayscalars.h"
-
-#include "arrayobject.h"
-#include "arrayctors.h"
-#include "arraymethods.h"
-#include "arraydescr.h"
-#include "arrayiterators.h"
-#include "arraymapping.h"
-#include "arraygetset.h"
-#include "arraysequence.h"
-
-#ifndef Py_UNICODE_WIDE
-#include "ucsnarrow.h"
-#endif
-
-
-
-/*NUMPY_API
- * Get Priority from object
- */
-NPY_NO_EXPORT double
-PyArray_GetPriority(PyObject *obj, double default_)
-{
- PyObject *ret;
- double priority = PyArray_PRIORITY;
-
- if (PyArray_CheckExact(obj))
- return priority;
-
- ret = PyObject_GetAttrString(obj, "__array_priority__");
- if (ret != NULL) {
- priority = PyFloat_AsDouble(ret);
- }
- if (PyErr_Occurred()) {
- PyErr_Clear();
- priority = default_;
- }
- Py_XDECREF(ret);
- return priority;
-}
-
-/* Incref all objects found at this record */
-/*NUMPY_API
- */
-NPY_NO_EXPORT void
-PyArray_Item_INCREF(char *data, PyArray_Descr *descr)
-{
- PyObject **temp;
-
- if (!PyDataType_REFCHK(descr)) {
- return;
- }
- if (descr->type_num == PyArray_OBJECT) {
- temp = (PyObject **)data;
- Py_XINCREF(*temp);
- }
- else if (PyDescr_HASFIELDS(descr)) {
- PyObject *key, *value, *title = NULL;
- PyArray_Descr *new;
- int offset;
- Py_ssize_t pos = 0;
-
- while (PyDict_Next(descr->fields, &pos, &key, &value)) {
- if NPY_TITLE_KEY(key, value) {
- continue;
- }
- if (!PyArg_ParseTuple(value, "Oi|O", &new, &offset,
- &title)) {
- return;
- }
- PyArray_Item_INCREF(data + offset, new);
- }
- }
- return;
-}
-
-/* XDECREF all objects found at this record */
-/*NUMPY_API
- */
-NPY_NO_EXPORT void
-PyArray_Item_XDECREF(char *data, PyArray_Descr *descr)
-{
- PyObject **temp;
-
- if (!PyDataType_REFCHK(descr)) {
- return;
- }
-
- if (descr->type_num == PyArray_OBJECT) {
- temp = (PyObject **)data;
- Py_XDECREF(*temp);
- }
- else if PyDescr_HASFIELDS(descr) {
- PyObject *key, *value, *title = NULL;
- PyArray_Descr *new;
- int offset;
- Py_ssize_t pos = 0;
-
- while (PyDict_Next(descr->fields, &pos, &key, &value)) {
- if NPY_TITLE_KEY(key, value) {
- continue;
- }
- if (!PyArg_ParseTuple(value, "Oi|O", &new, &offset,
- &title)) {
- return;
- }
- PyArray_Item_XDECREF(data + offset, new);
- }
- }
- return;
-}
-
-/* C-API functions */
-
-/* Used for arrays of python objects to increment the reference count of */
-/* every python object in the array. */
-/*NUMPY_API
- For object arrays, increment all internal references.
-*/
-NPY_NO_EXPORT int
-PyArray_INCREF(PyArrayObject *mp)
-{
- intp i, n;
- PyObject **data, **temp;
- PyArrayIterObject *it;
-
- if (!PyDataType_REFCHK(mp->descr)) {
- return 0;
- }
- if (mp->descr->type_num != PyArray_OBJECT) {
- it = (PyArrayIterObject *)PyArray_IterNew((PyObject *)mp);
- if (it == NULL) {
- return -1;
- }
- while(it->index < it->size) {
- PyArray_Item_INCREF(it->dataptr, mp->descr);
- PyArray_ITER_NEXT(it);
- }
- Py_DECREF(it);
- return 0;
- }
-
- if (PyArray_ISONESEGMENT(mp)) {
- data = (PyObject **)mp->data;
- n = PyArray_SIZE(mp);
- if (PyArray_ISALIGNED(mp)) {
- for (i = 0; i < n; i++, data++) {
- Py_XINCREF(*data);
- }
- }
- else {
- for( i = 0; i < n; i++, data++) {
- temp = data;
- Py_XINCREF(*temp);
- }
- }
- }
- else { /* handles misaligned data too */
- it = (PyArrayIterObject *)PyArray_IterNew((PyObject *)mp);
- if (it == NULL) {
- return -1;
- }
- while(it->index < it->size) {
- temp = (PyObject **)it->dataptr;
- Py_XINCREF(*temp);
- PyArray_ITER_NEXT(it);
- }
- Py_DECREF(it);
- }
- return 0;
-}
-
-/*NUMPY_API
- Decrement all internal references for object arrays.
- (or arrays with object fields)
-*/
-NPY_NO_EXPORT int
-PyArray_XDECREF(PyArrayObject *mp)
-{
- intp i, n;
- PyObject **data;
- PyObject **temp;
- PyArrayIterObject *it;
-
- if (!PyDataType_REFCHK(mp->descr)) {
- return 0;
- }
- if (mp->descr->type_num != PyArray_OBJECT) {
- it = (PyArrayIterObject *)PyArray_IterNew((PyObject *)mp);
- if (it == NULL) {
- return -1;
- }
- while(it->index < it->size) {
- PyArray_Item_XDECREF(it->dataptr, mp->descr);
- PyArray_ITER_NEXT(it);
- }
- Py_DECREF(it);
- return 0;
- }
-
- if (PyArray_ISONESEGMENT(mp)) {
- data = (PyObject **)mp->data;
- n = PyArray_SIZE(mp);
- if (PyArray_ISALIGNED(mp)) {
- for (i = 0; i < n; i++, data++) Py_XDECREF(*data);
- }
- else {
- for (i = 0; i < n; i++, data++) {
- temp = data;
- Py_XDECREF(*temp);
- }
- }
- }
- else { /* handles misaligned data too */
- it = (PyArrayIterObject *)PyArray_IterNew((PyObject *)mp);
- if (it == NULL) {
- return -1;
- }
- while(it->index < it->size) {
- temp = (PyObject **)it->dataptr;
- Py_XDECREF(*temp);
- PyArray_ITER_NEXT(it);
- }
- Py_DECREF(it);
- }
- return 0;
-}
-
-NPY_NO_EXPORT PyArray_Descr **userdescrs=NULL;
-
-
-/* Helper functions */
-
-/*NUMPY_API*/
-NPY_NO_EXPORT intp
-PyArray_PyIntAsIntp(PyObject *o)
-{
- longlong long_value = -1;
- PyObject *obj;
- static char *msg = "an integer is required";
- PyObject *arr;
- PyArray_Descr *descr;
- intp ret;
-
- if (!o) {
- PyErr_SetString(PyExc_TypeError, msg);
- return -1;
- }
- if (PyInt_Check(o)) {
- long_value = (longlong) PyInt_AS_LONG(o);
- goto finish;
- } else if (PyLong_Check(o)) {
- long_value = (longlong) PyLong_AsLongLong(o);
- goto finish;
- }
-
-#if SIZEOF_INTP == SIZEOF_LONG
- descr = &LONG_Descr;
-#elif SIZEOF_INTP == SIZEOF_INT
- descr = &INT_Descr;
-#else
- descr = &LONGLONG_Descr;
-#endif
- arr = NULL;
-
- if (PyArray_Check(o)) {
- if (PyArray_SIZE(o)!=1 || !PyArray_ISINTEGER(o)) {
- PyErr_SetString(PyExc_TypeError, msg);
- return -1;
- }
- Py_INCREF(descr);
- arr = PyArray_CastToType((PyArrayObject *)o, descr, 0);
- }
- else if (PyArray_IsScalar(o, Integer)) {
- Py_INCREF(descr);
- arr = PyArray_FromScalar(o, descr);
- }
- if (arr != NULL) {
- ret = *((intp *)PyArray_DATA(arr));
- Py_DECREF(arr);
- return ret;
- }
-
-#if (PY_VERSION_HEX >= 0x02050000)
- if (PyIndex_Check(o)) {
- PyObject* value = PyNumber_Index(o);
- if (value == NULL) {
- return -1;
- }
- long_value = (longlong) PyInt_AsSsize_t(value);
- goto finish;
- }
-#endif
- if (o->ob_type->tp_as_number != NULL && \
- o->ob_type->tp_as_number->nb_long != NULL) {
- obj = o->ob_type->tp_as_number->nb_long(o);
- if (obj != NULL) {
- long_value = (longlong) PyLong_AsLongLong(obj);
- Py_DECREF(obj);
- }
- }
- else if (o->ob_type->tp_as_number != NULL && \
- o->ob_type->tp_as_number->nb_int != NULL) {
- obj = o->ob_type->tp_as_number->nb_int(o);
- if (obj != NULL) {
- long_value = (longlong) PyLong_AsLongLong(obj);
- Py_DECREF(obj);
- }
- }
- else {
- PyErr_SetString(PyExc_NotImplementedError,"");
- }
-
- finish:
- if error_converting(long_value) {
- PyErr_SetString(PyExc_TypeError, msg);
- return -1;
- }
-
-#if (SIZEOF_LONGLONG > SIZEOF_INTP)
- if ((long_value < MIN_INTP) || (long_value > MAX_INTP)) {
- PyErr_SetString(PyExc_ValueError,
- "integer won't fit into a C intp");
- return -1;
- }
-#endif
- return (intp) long_value;
-}
-
-/*NUMPY_API*/
-NPY_NO_EXPORT int
-PyArray_PyIntAsInt(PyObject *o)
-{
- long long_value = -1;
- PyObject *obj;
- static char *msg = "an integer is required";
- PyObject *arr;
- PyArray_Descr *descr;
- int ret;
-
-
- if (!o) {
- PyErr_SetString(PyExc_TypeError, msg);
- return -1;
- }
- if (PyInt_Check(o)) {
- long_value = (long) PyInt_AS_LONG(o);
- goto finish;
- } else if (PyLong_Check(o)) {
- long_value = (long) PyLong_AsLong(o);
- goto finish;
- }
-
- descr = &INT_Descr;
- arr = NULL;
- if (PyArray_Check(o)) {
- if (PyArray_SIZE(o)!=1 || !PyArray_ISINTEGER(o)) {
- PyErr_SetString(PyExc_TypeError, msg);
- return -1;
- }
- Py_INCREF(descr);
- arr = PyArray_CastToType((PyArrayObject *)o, descr, 0);
- }
- if (PyArray_IsScalar(o, Integer)) {
- Py_INCREF(descr);
- arr = PyArray_FromScalar(o, descr);
- }
- if (arr != NULL) {
- ret = *((int *)PyArray_DATA(arr));
- Py_DECREF(arr);
- return ret;
- }
-#if (PY_VERSION_HEX >= 0x02050000)
- if (PyIndex_Check(o)) {
- PyObject* value = PyNumber_Index(o);
- long_value = (longlong) PyInt_AsSsize_t(value);
- goto finish;
- }
-#endif
- if (o->ob_type->tp_as_number != NULL && \
- o->ob_type->tp_as_number->nb_int != NULL) {
- obj = o->ob_type->tp_as_number->nb_int(o);
- if (obj == NULL) {
- return -1;
- }
- long_value = (long) PyLong_AsLong(obj);
- Py_DECREF(obj);
- }
- else if (o->ob_type->tp_as_number != NULL && \
- o->ob_type->tp_as_number->nb_long != NULL) {
- obj = o->ob_type->tp_as_number->nb_long(o);
- if (obj == NULL) {
- return -1;
- }
- long_value = (long) PyLong_AsLong(obj);
- Py_DECREF(obj);
- }
- else {
- PyErr_SetString(PyExc_NotImplementedError,"");
- }
-
- finish:
- if error_converting(long_value) {
- PyErr_SetString(PyExc_TypeError, msg);
- return -1;
- }
-
-#if (SIZEOF_LONG > SIZEOF_INT)
- if ((long_value < INT_MIN) || (long_value > INT_MAX)) {
- PyErr_SetString(PyExc_ValueError, "integer won't fit into a C int");
- return -1;
- }
-#endif
- return (int) long_value;
-}
-
-NPY_NO_EXPORT char *
-index2ptr(PyArrayObject *mp, intp i)
-{
- intp dim0;
-
- if (mp->nd == 0) {
- PyErr_SetString(PyExc_IndexError, "0-d arrays can't be indexed");
- return NULL;
- }
- dim0 = mp->dimensions[0];
- if (i < 0) {
- i += dim0;
- }
- if (i == 0 && dim0 > 0) {
- return mp->data;
- }
- if (i > 0 && i < dim0) {
- return mp->data+i*mp->strides[0];
- }
- PyErr_SetString(PyExc_IndexError,"index out of bounds");
- return NULL;
-}
-
-/*NUMPY_API
- Compute the size of an array (in number of items)
-*/
-NPY_NO_EXPORT intp
-PyArray_Size(PyObject *op)
-{
- if (PyArray_Check(op)) {
- return PyArray_SIZE((PyArrayObject *)op);
- }
- else {
- return 0;
- }
-}
-
-/*NUMPY_API*/
-NPY_NO_EXPORT int
-PyArray_CopyObject(PyArrayObject *dest, PyObject *src_object)
-{
- PyArrayObject *src;
- PyObject *r;
- int ret;
-
- /*
- * Special code to mimic Numeric behavior for
- * character arrays.
- */
- if (dest->descr->type == PyArray_CHARLTR && dest->nd > 0 \
- && PyString_Check(src_object)) {
- intp n_new, n_old;
- char *new_string;
- PyObject *tmp;
-
- n_new = dest->dimensions[dest->nd-1];
- n_old = PyString_Size(src_object);
- if (n_new > n_old) {
- new_string = (char *)malloc(n_new);
- memmove(new_string, PyString_AS_STRING(src_object), n_old);
- memset(new_string + n_old, ' ', n_new - n_old);
- tmp = PyString_FromStringAndSize(new_string, n_new);
- free(new_string);
- src_object = tmp;
- }
- }
-
- if (PyArray_Check(src_object)) {
- src = (PyArrayObject *)src_object;
- Py_INCREF(src);
- }
- else if (!PyArray_IsScalar(src_object, Generic) &&
- PyArray_HasArrayInterface(src_object, r)) {
- src = (PyArrayObject *)r;
- }
- else {
- PyArray_Descr* dtype;
- dtype = dest->descr;
- Py_INCREF(dtype);
- src = (PyArrayObject *)PyArray_FromAny(src_object, dtype, 0,
- dest->nd,
- FORTRAN_IF(dest),
- NULL);
- }
- if (src == NULL) {
- return -1;
- }
-
- ret = PyArray_MoveInto(dest, src);
- Py_DECREF(src);
- return ret;
-}
-
-
-/* Does nothing with descr (cannot be NULL) */
-/*NUMPY_API
- Get scalar-equivalent to a region of memory described by a descriptor.
-*/
-NPY_NO_EXPORT PyObject *
-PyArray_Scalar(void *data, PyArray_Descr *descr, PyObject *base)
-{
- PyTypeObject *type;
- PyObject *obj;
- void *destptr;
- PyArray_CopySwapFunc *copyswap;
- int type_num;
- int itemsize;
- int swap;
-
- type_num = descr->type_num;
- if (type_num == PyArray_BOOL) {
- PyArrayScalar_RETURN_BOOL_FROM_LONG(*(Bool*)data);
- }
- else if (PyDataType_FLAGCHK(descr, NPY_USE_GETITEM)) {
- return descr->f->getitem(data, base);
- }
- itemsize = descr->elsize;
- copyswap = descr->f->copyswap;
- type = descr->typeobj;
- swap = !PyArray_ISNBO(descr->byteorder);
- if PyTypeNum_ISSTRING(type_num) { /* Eliminate NULL bytes */
- char *dptr = data;
-
- dptr += itemsize - 1;
- while(itemsize && *dptr-- == 0) {
- itemsize--;
- }
- if (type_num == PyArray_UNICODE && itemsize) {
- /* make sure itemsize is a multiple of 4 */
- /* so round up to nearest multiple */
- itemsize = (((itemsize-1) >> 2) + 1) << 2;
- }
- }
- if (type->tp_itemsize != 0) { /* String type */
- obj = type->tp_alloc(type, itemsize);
- }
- else {
- obj = type->tp_alloc(type, 0);
- }
- if (obj == NULL) {
- return NULL;
- }
- if PyTypeNum_ISFLEXIBLE(type_num) {
- if (type_num == PyArray_STRING) {
- destptr = PyString_AS_STRING(obj);
- ((PyStringObject *)obj)->ob_shash = -1;
- ((PyStringObject *)obj)->ob_sstate = \
- SSTATE_NOT_INTERNED;
- memcpy(destptr, data, itemsize);
- return obj;
- }
- else if (type_num == PyArray_UNICODE) {
- PyUnicodeObject *uni = (PyUnicodeObject*)obj;
- size_t length = itemsize >> 2;
-#ifndef Py_UNICODE_WIDE
- char *buffer;
- int alloc = 0;
- length *= 2;
-#endif
- /* Need an extra slot and need to use
- Python memory manager */
- uni->str = NULL;
- destptr = PyMem_NEW(Py_UNICODE,length+1);
- if (destptr == NULL) {
- Py_DECREF(obj);
- return PyErr_NoMemory();
- }
- uni->str = (Py_UNICODE *)destptr;
- uni->str[0] = 0;
- uni->str[length] = 0;
- uni->length = length;
- uni->hash = -1;
- uni->defenc = NULL;
-#ifdef Py_UNICODE_WIDE
- memcpy(destptr, data, itemsize);
- if (swap) {
- byte_swap_vector(destptr, length, 4);
- }
-#else
- /* need aligned data buffer */
- if ((swap) || ((((intp)data) % descr->alignment) != 0)) {
- buffer = _pya_malloc(itemsize);
- if (buffer == NULL) {
- return PyErr_NoMemory();
- }
- alloc = 1;
- memcpy(buffer, data, itemsize);
- if (swap) {
- byte_swap_vector(buffer, itemsize >> 2, 4);
- }
- }
- else {
- buffer = data;
- }
-
- /* Allocated enough for 2-characters per itemsize.
- Now convert from the data-buffer
- */
- length = PyUCS2Buffer_FromUCS4(uni->str,
- (PyArray_UCS4 *)buffer,
- itemsize >> 2);
- if (alloc) {
- _pya_free(buffer);
- }
- /* Resize the unicode result */
- if (MyPyUnicode_Resize(uni, length) < 0) {
- Py_DECREF(obj);
- return NULL;
- }
-#endif
- return obj;
- }
- else {
- PyVoidScalarObject *vobj = (PyVoidScalarObject *)obj;
- vobj->base = NULL;
- vobj->descr = descr;
- Py_INCREF(descr);
- vobj->obval = NULL;
- vobj->ob_size = itemsize;
- vobj->flags = BEHAVED | OWNDATA;
- swap = 0;
- if (descr->names) {
- if (base) {
- Py_INCREF(base);
- vobj->base = base;
- vobj->flags = PyArray_FLAGS(base);
- vobj->flags &= ~OWNDATA;
- vobj->obval = data;
- return obj;
- }
- }
- destptr = PyDataMem_NEW(itemsize);
- if (destptr == NULL) {
- Py_DECREF(obj);
- return PyErr_NoMemory();
- }
- vobj->obval = destptr;
- }
- }
- else {
- destptr = scalar_value(obj, descr);
- }
- /* copyswap for OBJECT increments the reference count */
- copyswap(destptr, data, swap, base);
- return obj;
-}
-
-/* returns an Array-Scalar Object of the type of arr
- from the given pointer to memory -- main Scalar creation function
- default new method calls this.
-*/
-
-/* Ideally, here the descriptor would contain all the information needed.
- So, that we simply need the data and the descriptor, and perhaps
- a flag
-*/
-
-
-/* Return Array Scalar if 0-d array object is encountered */
-
-/*NUMPY_API
- Return either an array or the appropriate Python object if the array
- is 0d and matches a Python type.
-*/
-NPY_NO_EXPORT PyObject *
-PyArray_Return(PyArrayObject *mp)
-{
-
- if (mp == NULL) {
- return NULL;
- }
- if (PyErr_Occurred()) {
- Py_XDECREF(mp);
- return NULL;
- }
- if (!PyArray_Check(mp)) {
- return (PyObject *)mp;
- }
- if (mp->nd == 0) {
- PyObject *ret;
- ret = PyArray_ToScalar(mp->data, mp);
- Py_DECREF(mp);
- return ret;
- }
- else {
- return (PyObject *)mp;
- }
-}
-
-
-/*NUMPY_API
- Initialize arrfuncs to NULL
-*/
-NPY_NO_EXPORT void
-PyArray_InitArrFuncs(PyArray_ArrFuncs *f)
-{
- int i;
-
- for(i = 0; i < PyArray_NTYPES; i++) {
- f->cast[i] = NULL;
- }
- f->getitem = NULL;
- f->setitem = NULL;
- f->copyswapn = NULL;
- f->copyswap = NULL;
- f->compare = NULL;
- f->argmax = NULL;
- f->dotfunc = NULL;
- f->scanfunc = NULL;
- f->fromstr = NULL;
- f->nonzero = NULL;
- f->fill = NULL;
- f->fillwithscalar = NULL;
- for(i = 0; i < PyArray_NSORTS; i++) {
- f->sort[i] = NULL;
- f->argsort[i] = NULL;
- }
- f->castdict = NULL;
- f->scalarkind = NULL;
- f->cancastscalarkindto = NULL;
- f->cancastto = NULL;
-}
-
-static Bool
-_default_nonzero(void *ip, void *arr)
-{
- int elsize = PyArray_ITEMSIZE(arr);
- char *ptr = ip;
- while (elsize--) {
- if (*ptr++ != 0) {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-static void
-_default_copyswapn(void *dst, npy_intp dstride, void *src,
- npy_intp sstride, npy_intp n, int swap, void *arr)
-{
- npy_intp i;
- PyArray_CopySwapFunc *copyswap;
- char *dstptr = dst;
- char *srcptr = src;
-
- copyswap = PyArray_DESCR(arr)->f->copyswap;
-
- for (i = 0; i < n; i++) {
- copyswap(dstptr, srcptr, swap, arr);
- dstptr += dstride;
- srcptr += sstride;
- }
-}
-
-/*
- Given a string return the type-number for
- the data-type with that string as the type-object name.
- Returns PyArray_NOTYPE without setting an error if no type can be
- found. Only works for user-defined data-types.
-*/
-
-/*NUMPY_API
- */
-NPY_NO_EXPORT int
-PyArray_TypeNumFromName(char *str)
-{
- int i;
- PyArray_Descr *descr;
-
- for (i = 0; i < NPY_NUMUSERTYPES; i++) {
- descr = userdescrs[i];
- if (strcmp(descr->typeobj->tp_name, str) == 0) {
- return descr->type_num;
- }
- }
- return PyArray_NOTYPE;
-}
-
-/*
- returns typenum to associate with this type >=PyArray_USERDEF.
- needs the userdecrs table and PyArray_NUMUSER variables
- defined in arraytypes.inc
-*/
-/*NUMPY_API
- Register Data type
- Does not change the reference count of descr
-*/
-NPY_NO_EXPORT int
-PyArray_RegisterDataType(PyArray_Descr *descr)
-{
- PyArray_Descr *descr2;
- int typenum;
- int i;
- PyArray_ArrFuncs *f;
-
- /* See if this type is already registered */
- for (i = 0; i < NPY_NUMUSERTYPES; i++) {
- descr2 = userdescrs[i];
- if (descr2 == descr) {
- return descr->type_num;
- }
- }
- typenum = PyArray_USERDEF + NPY_NUMUSERTYPES;
- descr->type_num = typenum;
- if (descr->elsize == 0) {
- PyErr_SetString(PyExc_ValueError, "cannot register a" \
- "flexible data-type");
- return -1;
- }
- f = descr->f;
- if (f->nonzero == NULL) {
- f->nonzero = _default_nonzero;
- }
- if (f->copyswapn == NULL) {
- f->copyswapn = _default_copyswapn;
- }
- if (f->copyswap == NULL || f->getitem == NULL ||
- f->setitem == NULL) {
- PyErr_SetString(PyExc_ValueError, "a required array function" \
- " is missing.");
- return -1;
- }
- if (descr->typeobj == NULL) {
- PyErr_SetString(PyExc_ValueError, "missing typeobject");
- return -1;
- }
- userdescrs = realloc(userdescrs,
- (NPY_NUMUSERTYPES+1)*sizeof(void *));
- if (userdescrs == NULL) {
- PyErr_SetString(PyExc_MemoryError, "RegisterDataType");
- return -1;
- }
- userdescrs[NPY_NUMUSERTYPES++] = descr;
- return typenum;
-}
-
-/*NUMPY_API
- Register Casting Function
- Replaces any function currently stored.
-*/
-NPY_NO_EXPORT int
-PyArray_RegisterCastFunc(PyArray_Descr *descr, int totype,
- PyArray_VectorUnaryFunc *castfunc)
-{
- PyObject *cobj, *key;
- int ret;
-
- if (totype < PyArray_NTYPES) {
- descr->f->cast[totype] = castfunc;
- return 0;
- }
- if (!PyTypeNum_ISUSERDEF(totype)) {
- PyErr_SetString(PyExc_TypeError, "invalid type number.");
- return -1;
- }
- if (descr->f->castdict == NULL) {
- descr->f->castdict = PyDict_New();
- if (descr->f->castdict == NULL) {
- return -1;
- }
- }
- key = PyInt_FromLong(totype);
- if (PyErr_Occurred()) {
- return -1;
- }
- cobj = PyCObject_FromVoidPtr((void *)castfunc, NULL);
- if (cobj == NULL) {
- Py_DECREF(key);
- return -1;
- }
- ret = PyDict_SetItem(descr->f->castdict, key, cobj);
- Py_DECREF(key);
- Py_DECREF(cobj);
- return ret;
-}
-
-static int *
-_append_new(int *types, int insert)
-{
- int n = 0;
- int *newtypes;
-
- while (types[n] != PyArray_NOTYPE) {
- n++;
- }
- newtypes = (int *)realloc(types, (n + 2)*sizeof(int));
- newtypes[n] = insert;
- newtypes[n + 1] = PyArray_NOTYPE;
- return newtypes;
-}
-
-/*NUMPY_API
- * Register a type number indicating that a descriptor can be cast
- * to it safely
- */
-NPY_NO_EXPORT int
-PyArray_RegisterCanCast(PyArray_Descr *descr, int totype,
- NPY_SCALARKIND scalar)
-{
- if (scalar == PyArray_NOSCALAR) {
- /*
- * register with cancastto
- * These lists won't be freed once created
- * -- they become part of the data-type
- */
- if (descr->f->cancastto == NULL) {
- descr->f->cancastto = (int *)malloc(1*sizeof(int));
- descr->f->cancastto[0] = PyArray_NOTYPE;
- }
- descr->f->cancastto = _append_new(descr->f->cancastto,
- totype);
- }
- else {
- /* register with cancastscalarkindto */
- if (descr->f->cancastscalarkindto == NULL) {
- int i;
- descr->f->cancastscalarkindto =
- (int **)malloc(PyArray_NSCALARKINDS* sizeof(int*));
- for (i = 0; i < PyArray_NSCALARKINDS; i++) {
- descr->f->cancastscalarkindto[i] = NULL;
- }
- }
- if (descr->f->cancastscalarkindto[scalar] == NULL) {
- descr->f->cancastscalarkindto[scalar] =
- (int *)malloc(1*sizeof(int));
- descr->f->cancastscalarkindto[scalar][0] =
- PyArray_NOTYPE;
- }
- descr->f->cancastscalarkindto[scalar] =
- _append_new(descr->f->cancastscalarkindto[scalar], totype);
- }
- return 0;
-}
-
-/*********************** end C-API functions **********************/
-
-/* array object functions */
-
-static void
-array_dealloc(PyArrayObject *self) {
-
- if (self->weakreflist != NULL) {
- PyObject_ClearWeakRefs((PyObject *)self);
- }
- if (self->base) {
- /*
- * UPDATEIFCOPY means that base points to an
- * array that should be updated with the contents
- * of this array upon destruction.
- * self->base->flags must have been WRITEABLE
- * (checked previously) and it was locked here
- * thus, unlock it.
- */
- if (self->flags & UPDATEIFCOPY) {
- ((PyArrayObject *)self->base)->flags |= WRITEABLE;
- Py_INCREF(self); /* hold on to self in next call */
- if (PyArray_CopyAnyInto((PyArrayObject *)self->base, self) < 0) {
- PyErr_Print();
- PyErr_Clear();
- }
- /*
- * Don't need to DECREF -- because we are deleting
- *self already...
- */
- }
- /*
- * In any case base is pointing to something that we need
- * to DECREF -- either a view or a buffer object
- */
- Py_DECREF(self->base);
- }
-
- if ((self->flags & OWNDATA) && self->data) {
- /* Free internal references if an Object array */
- if (PyDataType_FLAGCHK(self->descr, NPY_ITEM_REFCOUNT)) {
- Py_INCREF(self); /*hold on to self */
- PyArray_XDECREF(self);
- /*
- * Don't need to DECREF -- because we are deleting
- * self already...
- */
- }
- PyDataMem_FREE(self->data);
- }
-
- PyDimMem_FREE(self->dimensions);
- Py_DECREF(self->descr);
- self->ob_type->tp_free((PyObject *)self);
-}
-
-/*************************************************************************
- **************** Implement Buffer Protocol ****************************
- *************************************************************************/
-
-/* removed multiple segment interface */
-
-static Py_ssize_t
-array_getsegcount(PyArrayObject *self, Py_ssize_t *lenp)
-{
- if (lenp) {
- *lenp = PyArray_NBYTES(self);
- }
- if (PyArray_ISONESEGMENT(self)) {
- return 1;
- }
- if (lenp) {
- *lenp = 0;
- }
- return 0;
-}
-
-static Py_ssize_t
-array_getreadbuf(PyArrayObject *self, Py_ssize_t segment, void **ptrptr)
-{
- if (segment != 0) {
- PyErr_SetString(PyExc_ValueError,
- "accessing non-existing array segment");
- return -1;
- }
- if (PyArray_ISONESEGMENT(self)) {
- *ptrptr = self->data;
- return PyArray_NBYTES(self);
- }
- PyErr_SetString(PyExc_ValueError, "array is not a single segment");
- *ptrptr = NULL;
- return -1;
-}
-
-
-static Py_ssize_t
-array_getwritebuf(PyArrayObject *self, Py_ssize_t segment, void **ptrptr)
-{
- if (PyArray_CHKFLAGS(self, WRITEABLE)) {
- return array_getreadbuf(self, segment, (void **) ptrptr);
- }
- else {
- PyErr_SetString(PyExc_ValueError, "array cannot be "
- "accessed as a writeable buffer");
- return -1;
- }
-}
-
-static Py_ssize_t
-array_getcharbuf(PyArrayObject *self, Py_ssize_t segment, constchar **ptrptr)
-{
- return array_getreadbuf(self, segment, (void **) ptrptr);
-}
-
-static PyBufferProcs array_as_buffer = {
-#if PY_VERSION_HEX >= 0x02050000
- (readbufferproc)array_getreadbuf, /*bf_getreadbuffer*/
- (writebufferproc)array_getwritebuf, /*bf_getwritebuffer*/
- (segcountproc)array_getsegcount, /*bf_getsegcount*/
- (charbufferproc)array_getcharbuf, /*bf_getcharbuffer*/
-#else
- (getreadbufferproc)array_getreadbuf, /*bf_getreadbuffer*/
- (getwritebufferproc)array_getwritebuf, /*bf_getwritebuffer*/
- (getsegcountproc)array_getsegcount, /*bf_getsegcount*/
- (getcharbufferproc)array_getcharbuf, /*bf_getcharbuffer*/
-#endif
-};
-
-/****************** End of Buffer Protocol *******************************/
-
-static int
-dump_data(char **string, int *n, int *max_n, char *data, int nd,
- intp *dimensions, intp *strides, PyArrayObject* self)
-{
- PyArray_Descr *descr=self->descr;
- PyObject *op, *sp;
- char *ostring;
- intp i, N;
-
-#define CHECK_MEMORY do { if (*n >= *max_n-16) { \
- *max_n *= 2; \
- *string = (char *)_pya_realloc(*string, *max_n); \
- }} while (0)
-
- if (nd == 0) {
- if ((op = descr->f->getitem(data, self)) == NULL) {
- return -1;
- }
- sp = PyObject_Repr(op);
- if (sp == NULL) {
- Py_DECREF(op);
- return -1;
- }
- ostring = PyString_AsString(sp);
- N = PyString_Size(sp)*sizeof(char);
- *n += N;
- CHECK_MEMORY;
- memmove(*string + (*n - N), ostring, N);
- Py_DECREF(sp);
- Py_DECREF(op);
- return 0;
- }
- else {
- CHECK_MEMORY;
- (*string)[*n] = '[';
- *n += 1;
- for (i = 0; i < dimensions[0]; i++) {
- if (dump_data(string, n, max_n,
- data + (*strides)*i,
- nd - 1, dimensions + 1,
- strides + 1, self) < 0) {
- return -1;
- }
- CHECK_MEMORY;
- if (i < dimensions[0] - 1) {
- (*string)[*n] = ',';
- (*string)[*n+1] = ' ';
- *n += 2;
- }
- }
- CHECK_MEMORY;
- (*string)[*n] = ']';
- *n += 1;
- return 0;
- }
-
-#undef CHECK_MEMORY
-}
-
-static PyObject *
-array_repr_builtin(PyArrayObject *self, int repr)
-{
- PyObject *ret;
- char *string;
- int n, max_n;
-
- max_n = PyArray_NBYTES(self)*4*sizeof(char) + 7;
-
- if ((string = (char *)_pya_malloc(max_n)) == NULL) {
- PyErr_SetString(PyExc_MemoryError, "out of memory");
- return NULL;
- }
-
- if (repr) {
- n = 6;
- sprintf(string, "array(");
- }
- else {
- n = 0;
- }
- if (dump_data(&string, &n, &max_n, self->data,
- self->nd, self->dimensions,
- self->strides, self) < 0) {
- _pya_free(string);
- return NULL;
- }
-
- if (repr) {
- if (PyArray_ISEXTENDED(self)) {
- char buf[100];
- PyOS_snprintf(buf, sizeof(buf), "%d", self->descr->elsize);
- sprintf(string+n, ", '%c%s')", self->descr->type, buf);
- ret = PyString_FromStringAndSize(string, n + 6 + strlen(buf));
- }
- else {
- sprintf(string+n, ", '%c')", self->descr->type);
- ret = PyString_FromStringAndSize(string, n+6);
- }
- }
- else {
- ret = PyString_FromStringAndSize(string, n);
- }
-
- _pya_free(string);
- return ret;
-}
-
-static PyObject *PyArray_StrFunction = NULL;
-static PyObject *PyArray_ReprFunction = NULL;
-
-/*NUMPY_API
- * Set the array print function to be a Python function.
- */
-NPY_NO_EXPORT void
-PyArray_SetStringFunction(PyObject *op, int repr)
-{
- if (repr) {
- /* Dispose of previous callback */
- Py_XDECREF(PyArray_ReprFunction);
- /* Add a reference to new callback */
- Py_XINCREF(op);
- /* Remember new callback */
- PyArray_ReprFunction = op;
- }
- else {
- /* Dispose of previous callback */
- Py_XDECREF(PyArray_StrFunction);
- /* Add a reference to new callback */
- Py_XINCREF(op);
- /* Remember new callback */
- PyArray_StrFunction = op;
- }
-}
-
-static PyObject *
-array_repr(PyArrayObject *self)
-{
- PyObject *s, *arglist;
-
- if (PyArray_ReprFunction == NULL) {
- s = array_repr_builtin(self, 1);
- }
- else {
- arglist = Py_BuildValue("(O)", self);
- s = PyEval_CallObject(PyArray_ReprFunction, arglist);
- Py_DECREF(arglist);
- }
- return s;
-}
-
-static PyObject *
-array_str(PyArrayObject *self)
-{
- PyObject *s, *arglist;
-
- if (PyArray_StrFunction == NULL) {
- s = array_repr_builtin(self, 0);
- }
- else {
- arglist = Py_BuildValue("(O)", self);
- s = PyEval_CallObject(PyArray_StrFunction, arglist);
- Py_DECREF(arglist);
- }
- return s;
-}
-
-
-
-/*NUMPY_API
- */
-NPY_NO_EXPORT int
-PyArray_CompareUCS4(npy_ucs4 *s1, npy_ucs4 *s2, size_t len)
-{
- PyArray_UCS4 c1, c2;
- while(len-- > 0) {
- c1 = *s1++;
- c2 = *s2++;
- if (c1 != c2) {
- return (c1 < c2) ? -1 : 1;
- }
- }
- return 0;
-}
-
-/*NUMPY_API
- */
-NPY_NO_EXPORT int
-PyArray_CompareString(char *s1, char *s2, size_t len)
-{
- const unsigned char *c1 = (unsigned char *)s1;
- const unsigned char *c2 = (unsigned char *)s2;
- size_t i;
-
- for(i = 0; i < len; ++i) {
- if (c1[i] != c2[i]) {
- return (c1[i] > c2[i]) ? 1 : -1;
- }
- }
- return 0;
-}
-
-
-/* This also handles possibly mis-aligned data */
-/* Compare s1 and s2 which are not necessarily NULL-terminated.
- s1 is of length len1
- s2 is of length len2
- If they are NULL terminated, then stop comparison.
-*/
-static int
-_myunincmp(PyArray_UCS4 *s1, PyArray_UCS4 *s2, int len1, int len2)
-{
- PyArray_UCS4 *sptr;
- PyArray_UCS4 *s1t=s1, *s2t=s2;
- int val;
- intp size;
- int diff;
-
- if ((intp)s1 % sizeof(PyArray_UCS4) != 0) {
- size = len1*sizeof(PyArray_UCS4);
- s1t = malloc(size);
- memcpy(s1t, s1, size);
- }
- if ((intp)s2 % sizeof(PyArray_UCS4) != 0) {
- size = len2*sizeof(PyArray_UCS4);
- s2t = malloc(size);
- memcpy(s2t, s2, size);
- }
- val = PyArray_CompareUCS4(s1t, s2t, MIN(len1,len2));
- if ((val != 0) || (len1 == len2)) {
- goto finish;
- }
- if (len2 > len1) {
- sptr = s2t+len1;
- val = -1;
- diff = len2-len1;
- }
- else {
- sptr = s1t+len2;
- val = 1;
- diff=len1-len2;
- }
- while (diff--) {
- if (*sptr != 0) {
- goto finish;
- }
- sptr++;
- }
- val = 0;
-
- finish:
- if (s1t != s1) {
- free(s1t);
- }
- if (s2t != s2) {
- free(s2t);
- }
- return val;
-}
-
-
-
-
-/*
- * Compare s1 and s2 which are not necessarily NULL-terminated.
- * s1 is of length len1
- * s2 is of length len2
- * If they are NULL terminated, then stop comparison.
- */
-static int
-_mystrncmp(char *s1, char *s2, int len1, int len2)
-{
- char *sptr;
- int val;
- int diff;
-
- val = memcmp(s1, s2, MIN(len1, len2));
- if ((val != 0) || (len1 == len2)) {
- return val;
- }
- if (len2 > len1) {
- sptr = s2 + len1;
- val = -1;
- diff = len2 - len1;
- }
- else {
- sptr = s1 + len2;
- val = 1;
- diff = len1 - len2;
- }
- while (diff--) {
- if (*sptr != 0) {
- return val;
- }
- sptr++;
- }
- return 0; /* Only happens if NULLs are everywhere */
-}
-
-/* Borrowed from Numarray */
-
-#define SMALL_STRING 2048
-
-#if defined(isspace)
-#undef isspace
-#define isspace(c) ((c==' ')||(c=='\t')||(c=='\n')||(c=='\r')||(c=='\v')||(c=='\f'))
-#endif
-
-static void _rstripw(char *s, int n)
-{
- int i;
- for (i = n - 1; i >= 1; i--) { /* Never strip to length 0. */
- int c = s[i];
-
- if (!c || isspace(c)) {
- s[i] = 0;
- }
- else {
- break;
- }
- }
-}
-
-static void _unistripw(PyArray_UCS4 *s, int n)
-{
- int i;
- for (i = n - 1; i >= 1; i--) { /* Never strip to length 0. */
- PyArray_UCS4 c = s[i];
- if (!c || isspace(c)) {
- s[i] = 0;
- }
- else {
- break;
- }
- }
-}
-
-
-static char *
-_char_copy_n_strip(char *original, char *temp, int nc)
-{
- if (nc > SMALL_STRING) {
- temp = malloc(nc);
- if (!temp) {
- PyErr_NoMemory();
- return NULL;
- }
- }
- memcpy(temp, original, nc);
- _rstripw(temp, nc);
- return temp;
-}
-
-static void
-_char_release(char *ptr, int nc)
-{
- if (nc > SMALL_STRING) {
- free(ptr);
- }
-}
-
-static char *
-_uni_copy_n_strip(char *original, char *temp, int nc)
-{
- if (nc*sizeof(PyArray_UCS4) > SMALL_STRING) {
- temp = malloc(nc*sizeof(PyArray_UCS4));
- if (!temp) {
- PyErr_NoMemory();
- return NULL;
- }
- }
- memcpy(temp, original, nc*sizeof(PyArray_UCS4));
- _unistripw((PyArray_UCS4 *)temp, nc);
- return temp;
-}
-
-static void
-_uni_release(char *ptr, int nc)
-{
- if (nc*sizeof(PyArray_UCS4) > SMALL_STRING) {
- free(ptr);
- }
-}
-
-
-/* End borrowed from numarray */
-
-#define _rstrip_loop(CMP) { \
- void *aptr, *bptr; \
- char atemp[SMALL_STRING], btemp[SMALL_STRING]; \
- while(size--) { \
- aptr = stripfunc(iself->dataptr, atemp, N1); \
- if (!aptr) return -1; \
- bptr = stripfunc(iother->dataptr, btemp, N2); \
- if (!bptr) { \
- relfunc(aptr, N1); \
- return -1; \
- } \
- val = cmpfunc(aptr, bptr, N1, N2); \
- *dptr = (val CMP 0); \
- PyArray_ITER_NEXT(iself); \
- PyArray_ITER_NEXT(iother); \
- dptr += 1; \
- relfunc(aptr, N1); \
- relfunc(bptr, N2); \
- } \
- }
-
-#define _reg_loop(CMP) { \
- while(size--) { \
- val = cmpfunc((void *)iself->dataptr, \
- (void *)iother->dataptr, \
- N1, N2); \
- *dptr = (val CMP 0); \
- PyArray_ITER_NEXT(iself); \
- PyArray_ITER_NEXT(iother); \
- dptr += 1; \
- } \
- }
-
-#define _loop(CMP) if (rstrip) _rstrip_loop(CMP) \
- else _reg_loop(CMP)
-
-static int
-_compare_strings(PyObject *result, PyArrayMultiIterObject *multi,
- int cmp_op, void *func, int rstrip)
-{
- PyArrayIterObject *iself, *iother;
- Bool *dptr;
- intp size;
- int val;
- int N1, N2;
- int (*cmpfunc)(void *, void *, int, int);
- void (*relfunc)(char *, int);
- char* (*stripfunc)(char *, char *, int);
-
- cmpfunc = func;
- dptr = (Bool *)PyArray_DATA(result);
- iself = multi->iters[0];
- iother = multi->iters[1];
- size = multi->size;
- N1 = iself->ao->descr->elsize;
- N2 = iother->ao->descr->elsize;
- if ((void *)cmpfunc == (void *)_myunincmp) {
- N1 >>= 2;
- N2 >>= 2;
- stripfunc = _uni_copy_n_strip;
- relfunc = _uni_release;
- }
- else {
- stripfunc = _char_copy_n_strip;
- relfunc = _char_release;
- }
- switch (cmp_op) {
- case Py_EQ:
- _loop(==)
- break;
- case Py_NE:
- _loop(!=)
- break;
- case Py_LT:
- _loop(<)
- break;
- case Py_LE:
- _loop(<=)
- break;
- case Py_GT:
- _loop(>)
- break;
- case Py_GE:
- _loop(>=)
- break;
- default:
- PyErr_SetString(PyExc_RuntimeError, "bad comparison operator");
- return -1;
- }
- return 0;
-}
-
-#undef _loop
-#undef _reg_loop
-#undef _rstrip_loop
-#undef SMALL_STRING
-
-NPY_NO_EXPORT PyObject *
-_strings_richcompare(PyArrayObject *self, PyArrayObject *other, int cmp_op,
- int rstrip)
-{
- PyObject *result;
- PyArrayMultiIterObject *mit;
- int val;
-
- /* Cast arrays to a common type */
- if (self->descr->type_num != other->descr->type_num) {
- PyObject *new;
- if (self->descr->type_num == PyArray_STRING &&
- other->descr->type_num == PyArray_UNICODE) {
- Py_INCREF(other->descr);
- new = PyArray_FromAny((PyObject *)self, other->descr,
- 0, 0, 0, NULL);
- if (new == NULL) {
- return NULL;
- }
- Py_INCREF(other);
- self = (PyArrayObject *)new;
- }
- else if (self->descr->type_num == PyArray_UNICODE &&
- other->descr->type_num == PyArray_STRING) {
- Py_INCREF(self->descr);
- new = PyArray_FromAny((PyObject *)other, self->descr,
- 0, 0, 0, NULL);
- if (new == NULL) {
- return NULL;
- }
- Py_INCREF(self);
- other = (PyArrayObject *)new;
- }
- else {
- PyErr_SetString(PyExc_TypeError,
- "invalid string data-types "
- "in comparison");
- return NULL;
- }
- }
- else {
- Py_INCREF(self);
- Py_INCREF(other);
- }
-
- /* Broad-cast the arrays to a common shape */
- mit = (PyArrayMultiIterObject *)PyArray_MultiIterNew(2, self, other);
- Py_DECREF(self);
- Py_DECREF(other);
- if (mit == NULL) {
- return NULL;
- }
-
- result = PyArray_NewFromDescr(&PyArray_Type,
- PyArray_DescrFromType(PyArray_BOOL),
- mit->nd,
- mit->dimensions,
- NULL, NULL, 0,
- NULL);
- if (result == NULL) {
- goto finish;
- }
-
- if (self->descr->type_num == PyArray_UNICODE) {
- val = _compare_strings(result, mit, cmp_op, _myunincmp, rstrip);
- }
- else {
- val = _compare_strings(result, mit, cmp_op, _mystrncmp, rstrip);
- }
-
- if (val < 0) {
- Py_DECREF(result); result = NULL;
- }
-
- finish:
- Py_DECREF(mit);
- return result;
-}
-
-/*
- * VOID-type arrays can only be compared equal and not-equal
- * in which case the fields are all compared by extracting the fields
- * and testing one at a time...
- * equality testing is performed using logical_ands on all the fields.
- * in-equality testing is performed using logical_ors on all the fields.
- *
- * VOID-type arrays without fields are compared for equality by comparing their
- * memory at each location directly (using string-code).
- */
-static PyObject *
-_void_compare(PyArrayObject *self, PyArrayObject *other, int cmp_op)
-{
- if (!(cmp_op == Py_EQ || cmp_op == Py_NE)) {
- PyErr_SetString(PyExc_ValueError,
- "Void-arrays can only be compared for equality.");
- return NULL;
- }
- if (PyArray_HASFIELDS(self)) {
- PyObject *res = NULL, *temp, *a, *b;
- PyObject *key, *value, *temp2;
- PyObject *op;
- Py_ssize_t pos = 0;
-
- op = (cmp_op == Py_EQ ? n_ops.logical_and : n_ops.logical_or);
- while (PyDict_Next(self->descr->fields, &pos, &key, &value)) {
- if NPY_TITLE_KEY(key, value) {
- continue;
- }
- a = PyArray_EnsureAnyArray(array_subscript(self, key));
- if (a == NULL) {
- Py_XDECREF(res);
- return NULL;
- }
- b = array_subscript(other, key);
- if (b == NULL) {
- Py_XDECREF(res);
- Py_DECREF(a);
- return NULL;
- }
- temp = array_richcompare((PyArrayObject *)a,b,cmp_op);
- Py_DECREF(a);
- Py_DECREF(b);
- if (temp == NULL) {
- Py_XDECREF(res);
- return NULL;
- }
- if (res == NULL) {
- res = temp;
- }
- else {
- temp2 = PyObject_CallFunction(op, "OO", res, temp);
- Py_DECREF(temp);
- Py_DECREF(res);
- if (temp2 == NULL) {
- return NULL;
- }
- res = temp2;
- }
- }
- if (res == NULL && !PyErr_Occurred()) {
- PyErr_SetString(PyExc_ValueError, "No fields found.");
- }
- return res;
- }
- else {
- /*
- * compare as a string. Assumes self and
- * other have same descr->type
- */
- return _strings_richcompare(self, other, cmp_op, 0);
- }
-}
-
-NPY_NO_EXPORT PyObject *
-array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
-{
- PyObject *array_other, *result = NULL;
- int typenum;
-
- switch (cmp_op) {
- case Py_LT:
- result = PyArray_GenericBinaryFunction(self, other,
- n_ops.less);
- break;
- case Py_LE:
- result = PyArray_GenericBinaryFunction(self, other,
- n_ops.less_equal);
- break;
- case Py_EQ:
- if (other == Py_None) {
- Py_INCREF(Py_False);
- return Py_False;
- }
- /* Try to convert other to an array */
- if (!PyArray_Check(other)) {
- typenum = self->descr->type_num;
- if (typenum != PyArray_OBJECT) {
- typenum = PyArray_NOTYPE;
- }
- array_other = PyArray_FromObject(other,
- typenum, 0, 0);
- /*
- * If not successful, then return False. This fixes code
- * that used to allow equality comparisons between arrays
- * and other objects which would give a result of False.
- */
- if ((array_other == NULL) ||
- (array_other == Py_None)) {
- Py_XDECREF(array_other);
- PyErr_Clear();
- Py_INCREF(Py_False);
- return Py_False;
- }
- }
- else {
- Py_INCREF(other);
- array_other = other;
- }
- result = PyArray_GenericBinaryFunction(self,
- array_other,
- n_ops.equal);
- if ((result == Py_NotImplemented) &&
- (self->descr->type_num == PyArray_VOID)) {
- int _res;
-
- _res = PyObject_RichCompareBool
- ((PyObject *)self->descr,
- (PyObject *)\
- PyArray_DESCR(array_other),
- Py_EQ);
- if (_res < 0) {
- Py_DECREF(result);
- Py_DECREF(array_other);
- return NULL;
- }
- if (_res) {
- Py_DECREF(result);
- result = _void_compare
- (self,
- (PyArrayObject *)array_other,
- cmp_op);
- Py_DECREF(array_other);
- }
- return result;
- }
- /*
- * If the comparison results in NULL, then the
- * two array objects can not be compared together so
- * return zero
- */
- Py_DECREF(array_other);
- if (result == NULL) {
- PyErr_Clear();
- Py_INCREF(Py_False);
- return Py_False;
- }
- break;
- case Py_NE:
- if (other == Py_None) {
- Py_INCREF(Py_True);
- return Py_True;
- }
- /* Try to convert other to an array */
- if (!PyArray_Check(other)) {
- typenum = self->descr->type_num;
- if (typenum != PyArray_OBJECT) {
- typenum = PyArray_NOTYPE;
- }
- array_other = PyArray_FromObject(other, typenum, 0, 0);
- /*
- * If not successful, then objects cannot be
- * compared and cannot be equal, therefore,
- * return True;
- */
- if ((array_other == NULL) || (array_other == Py_None)) {
- Py_XDECREF(array_other);
- PyErr_Clear();
- Py_INCREF(Py_True);
- return Py_True;
- }
- }
- else {
- Py_INCREF(other);
- array_other = other;
- }
- result = PyArray_GenericBinaryFunction(self,
- array_other,
- n_ops.not_equal);
- if ((result == Py_NotImplemented) &&
- (self->descr->type_num == PyArray_VOID)) {
- int _res;
-
- _res = PyObject_RichCompareBool(
- (PyObject *)self->descr,
- (PyObject *)
- PyArray_DESCR(array_other),
- Py_EQ);
- if (_res < 0) {
- Py_DECREF(result);
- Py_DECREF(array_other);
- return NULL;
- }
- if (_res) {
- Py_DECREF(result);
- result = _void_compare(
- self,
- (PyArrayObject *)array_other,
- cmp_op);
- Py_DECREF(array_other);
- }
- return result;
- }
-
- Py_DECREF(array_other);
- if (result == NULL) {
- PyErr_Clear();
- Py_INCREF(Py_True);
- return Py_True;
- }
- break;
- case Py_GT:
- result = PyArray_GenericBinaryFunction(self, other,
- n_ops.greater);
- break;
- case Py_GE:
- result = PyArray_GenericBinaryFunction(self, other,
- n_ops.greater_equal);
- break;
- default:
- result = Py_NotImplemented;
- Py_INCREF(result);
- }
- if (result == Py_NotImplemented) {
- /* Try to handle string comparisons */
- if (self->descr->type_num == PyArray_OBJECT) {
- return result;
- }
- array_other = PyArray_FromObject(other,PyArray_NOTYPE, 0, 0);
- if (PyArray_ISSTRING(self) && PyArray_ISSTRING(array_other)) {
- Py_DECREF(result);
- result = _strings_richcompare(self, (PyArrayObject *)
- array_other, cmp_op, 0);
- }
- Py_DECREF(array_other);
- }
- return result;
-}
-
-
-#define _check_axis PyArray_CheckAxis
-
-/* Lifted from numarray */
-/*NUMPY_API
- PyArray_IntTupleFromIntp
-*/
-NPY_NO_EXPORT PyObject *
-PyArray_IntTupleFromIntp(int len, intp *vals)
-{
- int i;
- PyObject *intTuple = PyTuple_New(len);
-
- if (!intTuple) {
- goto fail;
- }
- for (i = 0; i < len; i++) {
-#if SIZEOF_INTP <= SIZEOF_LONG
- PyObject *o = PyInt_FromLong((long) vals[i]);
-#else
- PyObject *o = PyLong_FromLongLong((longlong) vals[i]);
-#endif
- if (!o) {
- Py_DECREF(intTuple);
- intTuple = NULL;
- goto fail;
- }
- PyTuple_SET_ITEM(intTuple, i, o);
- }
-
- fail:
- return intTuple;
-}
-
-/*NUMPY_API
- * PyArray_IntpFromSequence
- * Returns the number of dimensions or -1 if an error occurred.
- * vals must be large enough to hold maxvals
- */
-NPY_NO_EXPORT int
-PyArray_IntpFromSequence(PyObject *seq, intp *vals, int maxvals)
-{
- int nd, i;
- PyObject *op, *err;
-
- /*
- * Check to see if sequence is a single integer first.
- * or, can be made into one
- */
- if ((nd=PySequence_Length(seq)) == -1) {
- if (PyErr_Occurred()) PyErr_Clear();
-#if SIZEOF_LONG >= SIZEOF_INTP
- if (!(op = PyNumber_Int(seq))) {
- return -1;
- }
-#else
- if (!(op = PyNumber_Long(seq))) {
- return -1;
- }
-#endif
- nd = 1;
-#if SIZEOF_LONG >= SIZEOF_INTP
- vals[0] = (intp ) PyInt_AsLong(op);
-#else
- vals[0] = (intp ) PyLong_AsLongLong(op);
-#endif
- Py_DECREF(op);
-
- /*
- * Check wether there was an error - if the error was an overflow, raise
- * a ValueError instead to be more helpful
- */
- if(vals[0] == -1) {
- err = PyErr_Occurred();
- if (err &&
- PyErr_GivenExceptionMatches(err, PyExc_OverflowError)) {
- PyErr_SetString(PyExc_ValueError,
- "Maximum allowed dimension exceeded");
- }
- if(err != NULL) {
- return -1;
- }
- }
- }
- else {
- for (i = 0; i < MIN(nd,maxvals); i++) {
- op = PySequence_GetItem(seq, i);
- if (op == NULL) {
- return -1;
- }
-#if SIZEOF_LONG >= SIZEOF_INTP
- vals[i]=(intp )PyInt_AsLong(op);
-#else
- vals[i]=(intp )PyLong_AsLongLong(op);
-#endif
- Py_DECREF(op);
-
- /*
- * Check wether there was an error - if the error was an overflow,
- * raise a ValueError instead to be more helpful
- */
- if(vals[0] == -1) {
- err = PyErr_Occurred();
- if (err &&
- PyErr_GivenExceptionMatches(err, PyExc_OverflowError)) {
- PyErr_SetString(PyExc_ValueError,
- "Maximum allowed dimension exceeded");
- }
- if(err != NULL) {
- return -1;
- }
- }
- }
- }
- return nd;
-}
-
-
-
-/*
- * Check whether the given array is stored contiguously
- * (row-wise) in memory.
- *
- * 0-strided arrays are not contiguous (even if dimension == 1)
- */
-static int
-_IsContiguous(PyArrayObject *ap)
-{
- intp sd;
- intp dim;
- int i;
-
- if (ap->nd == 0) {
- return 1;
- }
- sd = ap->descr->elsize;
- if (ap->nd == 1) {
- return ap->dimensions[0] == 1 || sd == ap->strides[0];
- }
- for (i = ap->nd - 1; i >= 0; --i) {
- dim = ap->dimensions[i];
- /* contiguous by definition */
- if (dim == 0) {
- return 1;
- }
- if (ap->strides[i] != sd) {
- return 0;
- }
- sd *= dim;
- }
- return 1;
-}
-
-
-/* 0-strided arrays are not contiguous (even if dimension == 1) */
-static int
-_IsFortranContiguous(PyArrayObject *ap)
-{
- intp sd;
- intp dim;
- int i;
-
- if (ap->nd == 0) {
- return 1;
- }
- sd = ap->descr->elsize;
- if (ap->nd == 1) {
- return ap->dimensions[0] == 1 || sd == ap->strides[0];
- }
- for (i = 0; i < ap->nd; ++i) {
- dim = ap->dimensions[i];
- /* fortran contiguous by definition */
- if (dim == 0) {
- return 1;
- }
- if (ap->strides[i] != sd) {
- return 0;
- }
- sd *= dim;
- }
- return 1;
-}
-
-NPY_NO_EXPORT int
-_IsAligned(PyArrayObject *ap)
-{
- int i, alignment, aligned = 1;
- intp ptr;
- int type = ap->descr->type_num;
-
- if ((type == PyArray_STRING) || (type == PyArray_VOID)) {
- return 1;
- }
- alignment = ap->descr->alignment;
- if (alignment == 1) {
- return 1;
- }
- ptr = (intp) ap->data;
- aligned = (ptr % alignment) == 0;
- for (i = 0; i < ap->nd; i++) {
- aligned &= ((ap->strides[i] % alignment) == 0);
- }
- return aligned != 0;
-}
-
-NPY_NO_EXPORT Bool
-_IsWriteable(PyArrayObject *ap)
-{
- PyObject *base=ap->base;
- void *dummy;
- Py_ssize_t n;
-
- /* If we own our own data, then no-problem */
- if ((base == NULL) || (ap->flags & OWNDATA)) {
- return TRUE;
- }
- /*
- * Get to the final base object
- * If it is a writeable array, then return TRUE
- * If we can find an array object
- * or a writeable buffer object as the final base object
- * or a string object (for pickling support memory savings).
- * - this last could be removed if a proper pickleable
- * buffer was added to Python.
- */
-
- while(PyArray_Check(base)) {
- if (PyArray_CHKFLAGS(base, OWNDATA)) {
- return (Bool) (PyArray_ISWRITEABLE(base));
- }
- base = PyArray_BASE(base);
- }
-
- /*
- * here so pickle support works seamlessly
- * and unpickled array can be set and reset writeable
- * -- could be abused --
- */
- if PyString_Check(base) {
- return TRUE;
- }
- if (PyObject_AsWriteBuffer(base, &dummy, &n) < 0) {
- return FALSE;
- }
- return TRUE;
-}
-
-
-/*NUMPY_API
- */
-NPY_NO_EXPORT int
-PyArray_ElementStrides(PyObject *arr)
-{
- int itemsize = PyArray_ITEMSIZE(arr);
- int i, N = PyArray_NDIM(arr);
- intp *strides = PyArray_STRIDES(arr);
-
- for (i = 0; i < N; i++) {
- if ((strides[i] % itemsize) != 0) {
- return 0;
- }
- }
- return 1;
-}
-
-/*NUMPY_API
- * Update Several Flags at once.
- */
-NPY_NO_EXPORT void
-PyArray_UpdateFlags(PyArrayObject *ret, int flagmask)
-{
-
- if (flagmask & FORTRAN) {
- if (_IsFortranContiguous(ret)) {
- ret->flags |= FORTRAN;
- if (ret->nd > 1) {
- ret->flags &= ~CONTIGUOUS;
- }
- }
- else {
- ret->flags &= ~FORTRAN;
- }
- }
- if (flagmask & CONTIGUOUS) {
- if (_IsContiguous(ret)) {
- ret->flags |= CONTIGUOUS;
- if (ret->nd > 1) {
- ret->flags &= ~FORTRAN;
- }
- }
- else {
- ret->flags &= ~CONTIGUOUS;
- }
- }
- if (flagmask & ALIGNED) {
- if (_IsAligned(ret)) {
- ret->flags |= ALIGNED;
- }
- else {
- ret->flags &= ~ALIGNED;
- }
- }
- /*
- * This is not checked by default WRITEABLE is not
- * part of UPDATE_ALL
- */
- if (flagmask & WRITEABLE) {
- if (_IsWriteable(ret)) {
- ret->flags |= WRITEABLE;
- }
- else {
- ret->flags &= ~WRITEABLE;
- }
- }
- return;
-}
-
-/*
- * This routine checks to see if newstrides (of length nd) will not
- * ever be able to walk outside of the memory implied numbytes and offset.
- *
- * The available memory is assumed to start at -offset and proceed
- * to numbytes-offset. The strides are checked to ensure
- * that accessing memory using striding will not try to reach beyond
- * this memory for any of the axes.
- *
- * If numbytes is 0 it will be calculated using the dimensions and
- * element-size.
- *
- * This function checks for walking beyond the beginning and right-end
- * of the buffer and therefore works for any integer stride (positive
- * or negative).
- */
-
-/*NUMPY_API*/
-NPY_NO_EXPORT Bool
-PyArray_CheckStrides(int elsize, int nd, intp numbytes, intp offset,
- intp *dims, intp *newstrides)
-{
- int i;
- intp byte_begin;
- intp begin;
- intp end;
-
- if (numbytes == 0) {
- numbytes = PyArray_MultiplyList(dims, nd) * elsize;
- }
- begin = -offset;
- end = numbytes - offset - elsize;
- for (i = 0; i < nd; i++) {
- byte_begin = newstrides[i]*(dims[i] - 1);
- if ((byte_begin < begin) || (byte_begin > end)) {
- return FALSE;
- }
- }
- return TRUE;
-}
-
-
-/*
- * This is the main array creation routine.
- *
- * Flags argument has multiple related meanings
- * depending on data and strides:
- *
- * If data is given, then flags is flags associated with data.
- * If strides is not given, then a contiguous strides array will be created
- * and the CONTIGUOUS bit will be set. If the flags argument
- * has the FORTRAN bit set, then a FORTRAN-style strides array will be
- * created (and of course the FORTRAN flag bit will be set).
- *
- * If data is not given but created here, then flags will be DEFAULT
- * and a non-zero flags argument can be used to indicate a FORTRAN style
- * array is desired.
- */
-
-NPY_NO_EXPORT size_t
-_array_fill_strides(intp *strides, intp *dims, int nd, size_t itemsize,
- int inflag, int *objflags)
-{
- int i;
- /* Only make Fortran strides if not contiguous as well */
- if ((inflag & FORTRAN) && !(inflag & CONTIGUOUS)) {
- for (i = 0; i < nd; i++) {
- strides[i] = itemsize;
- itemsize *= dims[i] ? dims[i] : 1;
- }
- *objflags |= FORTRAN;
- if (nd > 1) {
- *objflags &= ~CONTIGUOUS;
- }
- else {
- *objflags |= CONTIGUOUS;
- }
- }
- else {
- for (i = nd - 1; i >= 0; i--) {
- strides[i] = itemsize;
- itemsize *= dims[i] ? dims[i] : 1;
- }
- *objflags |= CONTIGUOUS;
- if (nd > 1) {
- *objflags &= ~FORTRAN;
- }
- else {
- *objflags |= FORTRAN;
- }
- }
- return itemsize;
-}
-
-static void
-_putzero(char *optr, PyObject *zero, PyArray_Descr *dtype)
-{
- if (!PyDataType_FLAGCHK(dtype, NPY_ITEM_REFCOUNT)) {
- memset(optr, 0, dtype->elsize);
- }
- else if (PyDescr_HASFIELDS(dtype)) {
- PyObject *key, *value, *title = NULL;
- PyArray_Descr *new;
- int offset;
- Py_ssize_t pos = 0;
- while (PyDict_Next(dtype->fields, &pos, &key, &value)) {
- if NPY_TITLE_KEY(key, value) {
- continue;
- }
- if (!PyArg_ParseTuple(value, "Oi|O", &new, &offset, &title)) {
- return;
- }
- _putzero(optr + offset, zero, new);
- }
- }
- else {
- PyObject **temp;
- Py_INCREF(zero);
- temp = (PyObject **)optr;
- *temp = zero;
- }
- return;
-}
-
-
-/*NUMPY_API
- * Resize (reallocate data). Only works if nothing else is referencing this
- * array and it is contiguous. If refcheck is 0, then the reference count is
- * not checked and assumed to be 1. You still must own this data and have no
- * weak-references and no base object.
- */
-NPY_NO_EXPORT PyObject *
-PyArray_Resize(PyArrayObject *self, PyArray_Dims *newshape, int refcheck,
- NPY_ORDER fortran)
-{
- intp oldsize, newsize;
- int new_nd=newshape->len, k, n, elsize;
- int refcnt;
- intp* new_dimensions=newshape->ptr;
- intp new_strides[MAX_DIMS];
- size_t sd;
- intp *dimptr;
- char *new_data;
- intp largest;
-
- if (!PyArray_ISONESEGMENT(self)) {
- PyErr_SetString(PyExc_ValueError,
- "resize only works on single-segment arrays");
- return NULL;
- }
-
- if (fortran == PyArray_ANYORDER) {
- fortran = PyArray_CORDER;
- }
- if (self->descr->elsize == 0) {
- PyErr_SetString(PyExc_ValueError, "Bad data-type size.");
- return NULL;
- }
- newsize = 1;
- largest = MAX_INTP / self->descr->elsize;
- for(k=0; k<new_nd; k++) {
- if (new_dimensions[k]==0) {
- break;
- }
- if (new_dimensions[k] < 0) {
- PyErr_SetString(PyExc_ValueError,
- "negative dimensions not allowed");
- return NULL;
- }
- newsize *= new_dimensions[k];
- if (newsize <=0 || newsize > largest) {
- return PyErr_NoMemory();
- }
- }
- oldsize = PyArray_SIZE(self);
-
- if (oldsize != newsize) {
- if (!(self->flags & OWNDATA)) {
- PyErr_SetString(PyExc_ValueError,
- "cannot resize this array: " \
- "it does not own its data");
- return NULL;
- }
-
- if (refcheck) {
- refcnt = REFCOUNT(self);
- }
- else {
- refcnt = 1;
- }
- if ((refcnt > 2) || (self->base != NULL) ||
- (self->weakreflist != NULL)) {
- PyErr_SetString(PyExc_ValueError,
- "cannot resize an array that has "\
- "been referenced or is referencing\n"\
- "another array in this way. Use the "\
- "resize function");
- return NULL;
- }
-
- if (newsize == 0) {
- sd = self->descr->elsize;
- }
- else {
- sd = newsize*self->descr->elsize;
- }
- /* Reallocate space if needed */
- new_data = PyDataMem_RENEW(self->data, sd);
- if (new_data == NULL) {
- PyErr_SetString(PyExc_MemoryError,
- "cannot allocate memory for array");
- return NULL;
- }
- self->data = new_data;
- }
-
- if ((newsize > oldsize) && PyArray_ISWRITEABLE(self)) {
- /* Fill new memory with zeros */
- elsize = self->descr->elsize;
- if (PyDataType_FLAGCHK(self->descr, NPY_ITEM_REFCOUNT)) {
- PyObject *zero = PyInt_FromLong(0);
- char *optr;
- optr = self->data + oldsize*elsize;
- n = newsize - oldsize;
- for (k = 0; k < n; k++) {
- _putzero((char *)optr, zero, self->descr);
- optr += elsize;
- }
- Py_DECREF(zero);
- }
- else{
- memset(self->data+oldsize*elsize, 0, (newsize-oldsize)*elsize);
- }
- }
-
- if (self->nd != new_nd) {
- /* Different number of dimensions. */
- self->nd = new_nd;
- /* Need new dimensions and strides arrays */
- dimptr = PyDimMem_RENEW(self->dimensions, 2*new_nd);
- if (dimptr == NULL) {
- PyErr_SetString(PyExc_MemoryError,
- "cannot allocate memory for array " \
- "(array may be corrupted)");
- return NULL;
- }
- self->dimensions = dimptr;
- self->strides = dimptr + new_nd;
- }
-
- /* make new_strides variable */
- sd = (size_t) self->descr->elsize;
- sd = (size_t) _array_fill_strides(new_strides, new_dimensions, new_nd, sd,
- self->flags, &(self->flags));
- memmove(self->dimensions, new_dimensions, new_nd*sizeof(intp));
- memmove(self->strides, new_strides, new_nd*sizeof(intp));
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static void
-_fillobject(char *optr, PyObject *obj, PyArray_Descr *dtype)
-{
- if (!PyDataType_FLAGCHK(dtype, NPY_ITEM_REFCOUNT)) {
- if ((obj == Py_None) || (PyInt_Check(obj) && PyInt_AsLong(obj)==0)) {
- return;
- }
- else {
- PyObject *arr;
- Py_INCREF(dtype);
- arr = PyArray_NewFromDescr(&PyArray_Type, dtype,
- 0, NULL, NULL, NULL,
- 0, NULL);
- if (arr!=NULL) {
- dtype->f->setitem(obj, optr, arr);
- }
- Py_XDECREF(arr);
- }
- }
- else if (PyDescr_HASFIELDS(dtype)) {
- PyObject *key, *value, *title = NULL;
- PyArray_Descr *new;
- int offset;
- Py_ssize_t pos = 0;
-
- while (PyDict_Next(dtype->fields, &pos, &key, &value)) {
- if NPY_TITLE_KEY(key, value) {
- continue;
- }
- if (!PyArg_ParseTuple(value, "Oi|O", &new, &offset, &title)) {
- return;
- }
- _fillobject(optr + offset, obj, new);
- }
- }
- else {
- PyObject **temp;
- Py_XINCREF(obj);
- temp = (PyObject **)optr;
- *temp = obj;
- return;
- }
-}
-
-/*NUMPY_API
- * Assumes contiguous
- */
-NPY_NO_EXPORT void
-PyArray_FillObjectArray(PyArrayObject *arr, PyObject *obj)
-{
- intp i,n;
- n = PyArray_SIZE(arr);
- if (arr->descr->type_num == PyArray_OBJECT) {
- PyObject **optr;
- optr = (PyObject **)(arr->data);
- n = PyArray_SIZE(arr);
- if (obj == NULL) {
- for (i = 0; i < n; i++) {
- *optr++ = NULL;
- }
- }
- else {
- for (i = 0; i < n; i++) {
- Py_INCREF(obj);
- *optr++ = obj;
- }
- }
- }
- else {
- char *optr;
- optr = arr->data;
- for (i = 0; i < n; i++) {
- _fillobject(optr, obj, arr->descr);
- optr += arr->descr->elsize;
- }
- }
-}
-
-static PyObject *
-array_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
-{
- static char *kwlist[] = {"shape", "dtype", "buffer",
- "offset", "strides",
- "order", NULL};
- PyArray_Descr *descr=NULL;
- int itemsize;
- PyArray_Dims dims = {NULL, 0};
- PyArray_Dims strides = {NULL, 0};
- PyArray_Chunk buffer;
- longlong offset=0;
- NPY_ORDER order=PyArray_CORDER;
- int fortran = 0;
- PyArrayObject *ret;
-
- buffer.ptr = NULL;
- /*
- * Usually called with shape and type but can also be called with buffer,
- * strides, and swapped info For now, let's just use this to create an
- * empty, contiguous array of a specific type and shape.
- */
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|O&O&LO&O&",
- kwlist, PyArray_IntpConverter,
- &dims,
- PyArray_DescrConverter,
- &descr,
- PyArray_BufferConverter,
- &buffer,
- &offset,
- &PyArray_IntpConverter,
- &strides,
- &PyArray_OrderConverter,
- &order)) {
- goto fail;
- }
- if (order == PyArray_FORTRANORDER) {
- fortran = 1;
- }
- if (descr == NULL) {
- descr = PyArray_DescrFromType(PyArray_DEFAULT);
- }
-
- itemsize = descr->elsize;
- if (itemsize == 0) {
- PyErr_SetString(PyExc_ValueError,
- "data-type with unspecified variable length");
- goto fail;
- }
-
- if (strides.ptr != NULL) {
- intp nb, off;
- if (strides.len != dims.len) {
- PyErr_SetString(PyExc_ValueError,
- "strides, if given, must be " \
- "the same length as shape");
- goto fail;
- }
-
- if (buffer.ptr == NULL) {
- nb = 0;
- off = 0;
- }
- else {
- nb = buffer.len;
- off = (intp) offset;
- }
-
-
- if (!PyArray_CheckStrides(itemsize, dims.len,
- nb, off,
- dims.ptr, strides.ptr)) {
- PyErr_SetString(PyExc_ValueError,
- "strides is incompatible " \
- "with shape of requested " \
- "array and size of buffer");
- goto fail;
- }
- }
-
- if (buffer.ptr == NULL) {
- ret = (PyArrayObject *)
- PyArray_NewFromDescr(subtype, descr,
- (int)dims.len,
- dims.ptr,
- strides.ptr, NULL, fortran, NULL);
- if (ret == NULL) {
- descr = NULL;
- goto fail;
- }
- if (PyDataType_FLAGCHK(descr, NPY_ITEM_HASOBJECT)) {
- /* place Py_None in object positions */
- PyArray_FillObjectArray(ret, Py_None);
- if (PyErr_Occurred()) {
- descr = NULL;
- goto fail;
- }
- }
- }
- else {
- /* buffer given -- use it */
- if (dims.len == 1 && dims.ptr[0] == -1) {
- dims.ptr[0] = (buffer.len-(intp)offset) / itemsize;
- }
- else if ((strides.ptr == NULL) &&
- (buffer.len < ((intp)itemsize)*
- PyArray_MultiplyList(dims.ptr, dims.len))) {
- PyErr_SetString(PyExc_TypeError,
- "buffer is too small for " \
- "requested array");
- goto fail;
- }
- /* get writeable and aligned */
- if (fortran) {
- buffer.flags |= FORTRAN;
- }
- ret = (PyArrayObject *)\
- PyArray_NewFromDescr(subtype, descr,
- dims.len, dims.ptr,
- strides.ptr,
- offset + (char *)buffer.ptr,
- buffer.flags, NULL);
- if (ret == NULL) {
- descr = NULL;
- goto fail;
- }
- PyArray_UpdateFlags(ret, UPDATE_ALL);
- ret->base = buffer.base;
- Py_INCREF(buffer.base);
- }
-
- PyDimMem_FREE(dims.ptr);
- if (strides.ptr) {
- PyDimMem_FREE(strides.ptr);
- }
- return (PyObject *)ret;
-
- fail:
- Py_XDECREF(descr);
- if (dims.ptr) {
- PyDimMem_FREE(dims.ptr);
- }
- if (strides.ptr) {
- PyDimMem_FREE(strides.ptr);
- }
- return NULL;
-}
-
-
-static PyObject *
-array_iter(PyArrayObject *arr)
-{
- if (arr->nd == 0) {
- PyErr_SetString(PyExc_TypeError,
- "iteration over a 0-d array");
- return NULL;
- }
- return PySeqIter_New((PyObject *)arr);
-}
-
-static PyObject *
-array_alloc(PyTypeObject *type, Py_ssize_t NPY_UNUSED(nitems))
-{
- PyObject *obj;
- /* nitems will always be 0 */
- obj = (PyObject *)_pya_malloc(sizeof(PyArrayObject));
- PyObject_Init(obj, type);
- return obj;
-}
-
-
-NPY_NO_EXPORT PyTypeObject PyArray_Type = {
- PyObject_HEAD_INIT(NULL)
- 0, /* ob_size */
- "numpy.ndarray", /* tp_name */
- sizeof(PyArrayObject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)array_dealloc, /* tp_dealloc */
- (printfunc)NULL, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- (cmpfunc)0, /* tp_compare */
- (reprfunc)array_repr, /* tp_repr */
- &array_as_number, /* tp_as_number */
- &array_as_sequence, /* tp_as_sequence */
- &array_as_mapping, /* tp_as_mapping */
- (hashfunc)0, /* tp_hash */
- (ternaryfunc)0, /* tp_call */
- (reprfunc)array_str, /* tp_str */
- (getattrofunc)0, /* tp_getattro */
- (setattrofunc)0, /* tp_setattro */
- &array_as_buffer, /* tp_as_buffer */
- (Py_TPFLAGS_DEFAULT
- | Py_TPFLAGS_BASETYPE
- | Py_TPFLAGS_CHECKTYPES), /* tp_flags */
- /*Documentation string */
- 0, /* tp_doc */
-
- (traverseproc)0, /* tp_traverse */
- (inquiry)0, /* tp_clear */
- (richcmpfunc)array_richcompare, /* tp_richcompare */
- offsetof(PyArrayObject, weakreflist), /* tp_weaklistoffset */
-
- /* Iterator support (use standard) */
-
- (getiterfunc)array_iter, /* tp_iter */
- (iternextfunc)0, /* tp_iternext */
-
- /* Sub-classing (new-style object) support */
-
- array_methods, /* tp_methods */
- 0, /* tp_members */
- array_getsetlist, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)0, /* tp_init */
- array_alloc, /* tp_alloc */
- (newfunc)array_new, /* tp_new */
- 0, /* tp_free */
- 0, /* tp_is_gc */
- 0, /* tp_bases */
- 0, /* tp_mro */
- 0, /* tp_cache */
- 0, /* tp_subclasses */
- 0, /* tp_weaklist */
- 0, /* tp_del */
-
-#ifdef COUNT_ALLOCS
- /* these must be last and never explicitly initialized */
- 0, /* tp_allocs */
- 0, /* tp_frees */
- 0, /* tp_maxalloc */
- 0, /* tp_prev */
- 0, /* *tp_next */
-#endif
-};
-
-
-/*
- * new reference
- * doesn't alter refcount of chktype or mintype ---
- * unless one of them is returned
- */
-NPY_NO_EXPORT PyArray_Descr *
-_array_small_type(PyArray_Descr *chktype, PyArray_Descr* mintype)
-{
- PyArray_Descr *outtype;
- int outtype_num, save_num;
-
- if (PyArray_EquivTypes(chktype, mintype)) {
- Py_INCREF(mintype);
- return mintype;
- }
-
-
- if (chktype->type_num > mintype->type_num) {
- outtype_num = chktype->type_num;
- }
- else {
- if (PyDataType_ISOBJECT(chktype) &&
- PyDataType_ISSTRING(mintype)) {
- return PyArray_DescrFromType(NPY_OBJECT);
- }
- else {
- outtype_num = mintype->type_num;
- }
- }
-
- save_num = outtype_num;
- while (outtype_num < PyArray_NTYPES &&
- !(PyArray_CanCastSafely(chktype->type_num, outtype_num)
- && PyArray_CanCastSafely(mintype->type_num, outtype_num))) {
- outtype_num++;
- }
- if (outtype_num == PyArray_NTYPES) {
- outtype = PyArray_DescrFromType(save_num);
- }
- else {
- outtype = PyArray_DescrFromType(outtype_num);
- }
- if (PyTypeNum_ISEXTENDED(outtype->type_num)) {
- int testsize = outtype->elsize;
- int chksize, minsize;
- chksize = chktype->elsize;
- minsize = mintype->elsize;
- /*
- * Handle string->unicode case separately
- * because string itemsize is 4* as large
- */
- if (outtype->type_num == PyArray_UNICODE &&
- mintype->type_num == PyArray_STRING) {
- testsize = MAX(chksize, 4*minsize);
- }
- else {
- testsize = MAX(chksize, minsize);
- }
- if (testsize != outtype->elsize) {
- PyArray_DESCR_REPLACE(outtype);
- outtype->elsize = testsize;
- Py_XDECREF(outtype->fields);
- outtype->fields = NULL;
- Py_XDECREF(outtype->names);
- outtype->names = NULL;
- }
- }
- return outtype;
-}
-
-NPY_NO_EXPORT PyArray_Descr *
-_array_find_python_scalar_type(PyObject *op)
-{
- if (PyFloat_Check(op)) {
- return PyArray_DescrFromType(PyArray_DOUBLE);
- }
- else if (PyComplex_Check(op)) {
- return PyArray_DescrFromType(PyArray_CDOUBLE);
- }
- else if (PyInt_Check(op)) {
- /* bools are a subclass of int */
- if (PyBool_Check(op)) {
- return PyArray_DescrFromType(PyArray_BOOL);
- }
- else {
- return PyArray_DescrFromType(PyArray_LONG);
- }
- }
- else if (PyLong_Check(op)) {
- /* if integer can fit into a longlong then return that*/
- if ((PyLong_AsLongLong(op) == -1) && PyErr_Occurred()) {
- PyErr_Clear();
- return PyArray_DescrFromType(PyArray_OBJECT);
- }
- return PyArray_DescrFromType(PyArray_LONGLONG);
- }
- return NULL;
-}
-
-static PyArray_Descr *
-_use_default_type(PyObject *op)
-{
- int typenum, l;
- PyObject *type;
-
- typenum = -1;
- l = 0;
- type = (PyObject *)op->ob_type;
- while (l < PyArray_NUMUSERTYPES) {
- if (type == (PyObject *)(userdescrs[l]->typeobj)) {
- typenum = l + PyArray_USERDEF;
- break;
- }
- l++;
- }
- if (typenum == -1) {
- typenum = PyArray_OBJECT;
- }
- return PyArray_DescrFromType(typenum);
-}
-
-
-/*
- * op is an object to be converted to an ndarray.
- *
- * minitype is the minimum type-descriptor needed.
- *
- * max is the maximum number of dimensions -- used for recursive call
- * to avoid infinite recursion...
- */
-NPY_NO_EXPORT PyArray_Descr *
-_array_find_type(PyObject *op, PyArray_Descr *minitype, int max)
-{
- int l;
- PyObject *ip;
- PyArray_Descr *chktype = NULL;
- PyArray_Descr *outtype;
-
- /*
- * These need to come first because if op already carries
- * a descr structure, then we want it to be the result if minitype
- * is NULL.
- */
- if (PyArray_Check(op)) {
- chktype = PyArray_DESCR(op);
- Py_INCREF(chktype);
- if (minitype == NULL) {
- return chktype;
- }
- Py_INCREF(minitype);
- goto finish;
- }
-
- if (PyArray_IsScalar(op, Generic)) {
- chktype = PyArray_DescrFromScalar(op);
- if (minitype == NULL) {
- return chktype;
- }
- Py_INCREF(minitype);
- goto finish;
- }
-
- if (minitype == NULL) {
- minitype = PyArray_DescrFromType(PyArray_BOOL);
- }
- else {
- Py_INCREF(minitype);
- }
- if (max < 0) {
- goto deflt;
- }
- chktype = _array_find_python_scalar_type(op);
- if (chktype) {
- goto finish;
- }
-
- if ((ip=PyObject_GetAttrString(op, "__array_interface__"))!=NULL) {
- if (PyDict_Check(ip)) {
- PyObject *new;
- new = PyDict_GetItemString(ip, "typestr");
- if (new && PyString_Check(new)) {
- chktype =_array_typedescr_fromstr(PyString_AS_STRING(new));
- }
- }
- Py_DECREF(ip);
- if (chktype) {
- goto finish;
- }
- }
- else {
- PyErr_Clear();
- }
- if ((ip=PyObject_GetAttrString(op, "__array_struct__")) != NULL) {
- PyArrayInterface *inter;
- char buf[40];
- if (PyCObject_Check(ip)) {
- inter=(PyArrayInterface *)PyCObject_AsVoidPtr(ip);
- if (inter->two == 2) {
- PyOS_snprintf(buf, sizeof(buf),
- "|%c%d", inter->typekind, inter->itemsize);
- chktype = _array_typedescr_fromstr(buf);
- }
- }
- Py_DECREF(ip);
- if (chktype) {
- goto finish;
- }
- }
- else {
- PyErr_Clear();
- }
-
- if (PyString_Check(op)) {
- chktype = PyArray_DescrNewFromType(PyArray_STRING);
- chktype->elsize = PyString_GET_SIZE(op);
- goto finish;
- }
-
- if (PyUnicode_Check(op)) {
- chktype = PyArray_DescrNewFromType(PyArray_UNICODE);
- chktype->elsize = PyUnicode_GET_DATA_SIZE(op);
-#ifndef Py_UNICODE_WIDE
- chktype->elsize <<= 1;
-#endif
- goto finish;
- }
-
- if (PyBuffer_Check(op)) {
- chktype = PyArray_DescrNewFromType(PyArray_VOID);
- chktype->elsize = op->ob_type->tp_as_sequence->sq_length(op);
- PyErr_Clear();
- goto finish;
- }
-
- if (PyObject_HasAttrString(op, "__array__")) {
- ip = PyObject_CallMethod(op, "__array__", NULL);
- if(ip && PyArray_Check(ip)) {
- chktype = PyArray_DESCR(ip);
- Py_INCREF(chktype);
- Py_DECREF(ip);
- goto finish;
- }
- Py_XDECREF(ip);
- if (PyErr_Occurred()) PyErr_Clear();
- }
-
- if (PyInstance_Check(op)) {
- goto deflt;
- }
- if (PySequence_Check(op)) {
- l = PyObject_Length(op);
- if (l < 0 && PyErr_Occurred()) {
- PyErr_Clear();
- goto deflt;
- }
- if (l == 0 && minitype->type_num == PyArray_BOOL) {
- Py_DECREF(minitype);
- minitype = PyArray_DescrFromType(PyArray_DEFAULT);
- }
- while (--l >= 0) {
- PyArray_Descr *newtype;
- ip = PySequence_GetItem(op, l);
- if (ip==NULL) {
- PyErr_Clear();
- goto deflt;
- }
- chktype = _array_find_type(ip, minitype, max-1);
- newtype = _array_small_type(chktype, minitype);
- Py_DECREF(minitype);
- minitype = newtype;
- Py_DECREF(chktype);
- Py_DECREF(ip);
- }
- chktype = minitype;
- Py_INCREF(minitype);
- goto finish;
- }
-
-
- deflt:
- chktype = _use_default_type(op);
-
- finish:
- outtype = _array_small_type(chktype, minitype);
- Py_DECREF(chktype);
- Py_DECREF(minitype);
- /*
- * VOID Arrays should not occur by "default"
- * unless input was already a VOID
- */
- if (outtype->type_num == PyArray_VOID &&
- minitype->type_num != PyArray_VOID) {
- Py_DECREF(outtype);
- return PyArray_DescrFromType(PyArray_OBJECT);
- }
- return outtype;
-}
-
-/* new reference */
-NPY_NO_EXPORT PyArray_Descr *
-_array_typedescr_fromstr(char *str)
-{
- PyArray_Descr *descr;
- int type_num;
- char typechar;
- int size;
- char msg[] = "unsupported typestring";
- int swap;
- char swapchar;
-
- swapchar = str[0];
- str += 1;
-
- typechar = str[0];
- size = atoi(str + 1);
- switch (typechar) {
- case 'b':
- if (size == sizeof(Bool)) {
- type_num = PyArray_BOOL;
- }
- else {
- PyErr_SetString(PyExc_ValueError, msg);
- return NULL;
- }
- break;
- case 'u':
- if (size == sizeof(uintp)) {
- type_num = PyArray_UINTP;
- }
- else if (size == sizeof(char)) {
- type_num = PyArray_UBYTE;
- }
- else if (size == sizeof(short)) {
- type_num = PyArray_USHORT;
- }
- else if (size == sizeof(ulong)) {
- type_num = PyArray_ULONG;
- }
- else if (size == sizeof(int)) {
- type_num = PyArray_UINT;
- }
- else if (size == sizeof(ulonglong)) {
- type_num = PyArray_ULONGLONG;
- }
- else {
- PyErr_SetString(PyExc_ValueError, msg);
- return NULL;
- }
- break;
- case 'i':
- if (size == sizeof(intp)) {
- type_num = PyArray_INTP;
- }
- else if (size == sizeof(char)) {
- type_num = PyArray_BYTE;
- }
- else if (size == sizeof(short)) {
- type_num = PyArray_SHORT;
- }
- else if (size == sizeof(long)) {
- type_num = PyArray_LONG;
- }
- else if (size == sizeof(int)) {
- type_num = PyArray_INT;
- }
- else if (size == sizeof(longlong)) {
- type_num = PyArray_LONGLONG;
- }
- else {
- PyErr_SetString(PyExc_ValueError, msg);
- return NULL;
- }
- break;
- case 'f':
- if (size == sizeof(float)) {
- type_num = PyArray_FLOAT;
- }
- else if (size == sizeof(double)) {
- type_num = PyArray_DOUBLE;
- }
- else if (size == sizeof(longdouble)) {
- type_num = PyArray_LONGDOUBLE;
- }
- else {
- PyErr_SetString(PyExc_ValueError, msg);
- return NULL;
- }
- break;
- case 'c':
- if (size == sizeof(float)*2) {
- type_num = PyArray_CFLOAT;
- }
- else if (size == sizeof(double)*2) {
- type_num = PyArray_CDOUBLE;
- }
- else if (size == sizeof(longdouble)*2) {
- type_num = PyArray_CLONGDOUBLE;
- }
- else {
- PyErr_SetString(PyExc_ValueError, msg);
- return NULL;
- }
- break;
- case 'O':
- if (size == sizeof(PyObject *)) {
- type_num = PyArray_OBJECT;
- }
- else {
- PyErr_SetString(PyExc_ValueError, msg);
- return NULL;
- }
- break;
- case PyArray_STRINGLTR:
- type_num = PyArray_STRING;
- break;
- case PyArray_UNICODELTR:
- type_num = PyArray_UNICODE;
- size <<= 2;
- break;
- case 'V':
- type_num = PyArray_VOID;
- break;
- default:
- PyErr_SetString(PyExc_ValueError, msg);
- return NULL;
- }
-
- descr = PyArray_DescrFromType(type_num);
- if (descr == NULL) {
- return NULL;
- }
- swap = !PyArray_ISNBO(swapchar);
- if (descr->elsize == 0 || swap) {
- /* Need to make a new PyArray_Descr */
- PyArray_DESCR_REPLACE(descr);
- if (descr==NULL) {
- return NULL;
- }
- if (descr->elsize == 0) {
- descr->elsize = size;
- }
- if (swap) {
- descr->byteorder = swapchar;
- }
- }
- return descr;
-}