diff options
Diffstat (limited to 'numpy/core/src/arrayobject.c')
-rw-r--r-- | numpy/core/src/arrayobject.c | 1163 |
1 files changed, 1 insertions, 1162 deletions
diff --git a/numpy/core/src/arrayobject.c b/numpy/core/src/arrayobject.c index e94608160..e831a2242 100644 --- a/numpy/core/src/arrayobject.c +++ b/numpy/core/src/arrayobject.c @@ -31,6 +31,7 @@ maintainer email: oliphant.travis@ieee.org #include "numpy/arrayscalars.h" #include "arrayobject.h" +#include "arraydescr.h" /*NUMPY_API * Get Priority from object @@ -6651,8 +6652,6 @@ array_priority_get(PyArrayObject *self) } } -static PyObject *arraydescr_protocol_typestr_get(PyArray_Descr *); - static PyObject * array_typestr_get(PyArrayObject *self) { @@ -6666,8 +6665,6 @@ array_descr_get(PyArrayObject *self) return (PyObject *)self->descr; } -static PyObject *arraydescr_protocol_descr_get(PyArray_Descr *self); - static PyObject * array_protocol_descr_get(PyArrayObject *self) { @@ -11896,1161 +11893,3 @@ NPY_NO_EXPORT PyTypeObject PyArrayMultiIter_Type = { 0, /* *tp_next */ #endif }; - -/*NUMPY_API*/ -NPY_NO_EXPORT PyArray_Descr * -PyArray_DescrNewFromType(int type_num) -{ - PyArray_Descr *old; - PyArray_Descr *new; - - old = PyArray_DescrFromType(type_num); - new = PyArray_DescrNew(old); - Py_DECREF(old); - return new; -} - -/** Array Descr Objects for dynamic types **/ - -/* - * There are some statically-defined PyArray_Descr objects corresponding - * to the basic built-in types. - * These can and should be DECREF'd and INCREF'd as appropriate, anyway. - * If a mistake is made in reference counting, deallocation on these - * builtins will be attempted leading to problems. - * - * This let's us deal with all PyArray_Descr objects using reference - * counting (regardless of whether they are statically or dynamically - * allocated). - */ - -/*NUMPY_API - * base cannot be NULL - */ -NPY_NO_EXPORT PyArray_Descr * -PyArray_DescrNew(PyArray_Descr *base) -{ - PyArray_Descr *new = PyObject_New(PyArray_Descr, &PyArrayDescr_Type); - - if (new == NULL) { - return NULL; - } - /* Don't copy PyObject_HEAD part */ - memcpy((char *)new + sizeof(PyObject), - (char *)base + sizeof(PyObject), - sizeof(PyArray_Descr) - sizeof(PyObject)); - - if (new->fields == Py_None) { - new->fields = NULL; - } - Py_XINCREF(new->fields); - Py_XINCREF(new->names); - if (new->subarray) { - new->subarray = _pya_malloc(sizeof(PyArray_ArrayDescr)); - memcpy(new->subarray, base->subarray, sizeof(PyArray_ArrayDescr)); - Py_INCREF(new->subarray->shape); - Py_INCREF(new->subarray->base); - } - Py_XINCREF(new->typeobj); - return new; -} - -/* - * should never be called for builtin-types unless - * there is a reference-count problem - */ -static void -arraydescr_dealloc(PyArray_Descr *self) -{ - if (self->fields == Py_None) { - fprintf(stderr, "*** Reference count error detected: \n" \ - "an attempt was made to deallocate %d (%c) ***\n", - self->type_num, self->type); - Py_INCREF(self); - Py_INCREF(self); - return; - } - Py_XDECREF(self->typeobj); - Py_XDECREF(self->names); - Py_XDECREF(self->fields); - if (self->subarray) { - Py_DECREF(self->subarray->shape); - Py_DECREF(self->subarray->base); - _pya_free(self->subarray); - } - self->ob_type->tp_free((PyObject *)self); -} - -/* - * we need to be careful about setting attributes because these - * objects are pointed to by arrays that depend on them for interpreting - * data. Currently no attributes of data-type objects can be set - * directly except names. - */ -static PyMemberDef arraydescr_members[] = { - {"type", - T_OBJECT, offsetof(PyArray_Descr, typeobj), RO, NULL}, - {"kind", - T_CHAR, offsetof(PyArray_Descr, kind), RO, NULL}, - {"char", - T_CHAR, offsetof(PyArray_Descr, type), RO, NULL}, - {"num", - T_INT, offsetof(PyArray_Descr, type_num), RO, NULL}, - {"byteorder", - T_CHAR, offsetof(PyArray_Descr, byteorder), RO, NULL}, - {"itemsize", - T_INT, offsetof(PyArray_Descr, elsize), RO, NULL}, - {"alignment", - T_INT, offsetof(PyArray_Descr, alignment), RO, NULL}, - {"flags", - T_UBYTE, offsetof(PyArray_Descr, hasobject), RO, NULL}, - {NULL, 0, 0, 0, NULL}, -}; - -static PyObject * -arraydescr_subdescr_get(PyArray_Descr *self) -{ - if (self->subarray == NULL) { - Py_INCREF(Py_None); - return Py_None; - } - return Py_BuildValue("OO", (PyObject *)self->subarray->base, - self->subarray->shape); -} - -static PyObject * -arraydescr_protocol_typestr_get(PyArray_Descr *self) -{ - char basic_ = self->kind; - char endian = self->byteorder; - int size = self->elsize; - - if (endian == '=') { - endian = '<'; - if (!PyArray_IsNativeByteOrder(endian)) { - endian = '>'; - } - } - if (self->type_num == PyArray_UNICODE) { - size >>= 2; - } - return PyString_FromFormat("%c%c%d", endian, basic_, size); -} - -static PyObject * -arraydescr_typename_get(PyArray_Descr *self) -{ - int len; - PyTypeObject *typeobj = self->typeobj; - PyObject *res; - char *s; - /* fixme: not reentrant */ - static int prefix_len = 0; - - if (PyTypeNum_ISUSERDEF(self->type_num)) { - s = strrchr(typeobj->tp_name, '.'); - if (s == NULL) { - res = PyString_FromString(typeobj->tp_name); - } - else { - res = PyString_FromStringAndSize(s + 1, strlen(s) - 1); - } - return res; - } - else { - if (prefix_len == 0) { - prefix_len = strlen("numpy."); - } - len = strlen(typeobj->tp_name); - if (*(typeobj->tp_name + (len-1)) == '_') { - len -= 1; - } - len -= prefix_len; - res = PyString_FromStringAndSize(typeobj->tp_name+prefix_len, len); - } - if (PyTypeNum_ISFLEXIBLE(self->type_num) && self->elsize != 0) { - PyObject *p; - p = PyString_FromFormat("%d", self->elsize * 8); - PyString_ConcatAndDel(&res, p); - } - return res; -} - -static PyObject * -arraydescr_base_get(PyArray_Descr *self) -{ - if (self->subarray == NULL) { - Py_INCREF(self); - return (PyObject *)self; - } - Py_INCREF(self->subarray->base); - return (PyObject *)(self->subarray->base); -} - -static PyObject * -arraydescr_shape_get(PyArray_Descr *self) -{ - if (self->subarray == NULL) { - return PyTuple_New(0); - } - if (PyTuple_Check(self->subarray->shape)) { - Py_INCREF(self->subarray->shape); - return (PyObject *)(self->subarray->shape); - } - return Py_BuildValue("(O)", self->subarray->shape); -} - -static PyObject * -arraydescr_protocol_descr_get(PyArray_Descr *self) -{ - PyObject *dobj, *res; - PyObject *_numpy_internal; - - if (self->names == NULL) { - /* get default */ - dobj = PyTuple_New(2); - if (dobj == NULL) { - return NULL; - } - PyTuple_SET_ITEM(dobj, 0, PyString_FromString("")); - PyTuple_SET_ITEM(dobj, 1, arraydescr_protocol_typestr_get(self)); - res = PyList_New(1); - if (res == NULL) { - Py_DECREF(dobj); - return NULL; - } - PyList_SET_ITEM(res, 0, dobj); - return res; - } - - _numpy_internal = PyImport_ImportModule("numpy.core._internal"); - if (_numpy_internal == NULL) { - return NULL; - } - res = PyObject_CallMethod(_numpy_internal, "_array_descr", "O", self); - Py_DECREF(_numpy_internal); - return res; -} - -/* - * returns 1 for a builtin type - * and 2 for a user-defined data-type descriptor - * return 0 if neither (i.e. it's a copy of one) - */ -static PyObject * -arraydescr_isbuiltin_get(PyArray_Descr *self) -{ - long val; - val = 0; - if (self->fields == Py_None) { - val = 1; - } - if (PyTypeNum_ISUSERDEF(self->type_num)) { - val = 2; - } - return PyInt_FromLong(val); -} - -static int -_arraydescr_isnative(PyArray_Descr *self) -{ - if (self->names == NULL) { - return PyArray_ISNBO(self->byteorder); - } - else { - PyObject *key, *value, *title = NULL; - PyArray_Descr *new; - int offset; - Py_ssize_t pos = 0; - while (PyDict_Next(self->fields, &pos, &key, &value)) { - if NPY_TITLE_KEY(key, value) { - continue; - } - if (!PyArg_ParseTuple(value, "Oi|O", &new, &offset, &title)) { - return -1; - } - if (!_arraydescr_isnative(new)) { - return 0; - } - } - } - return 1; -} - -/* - * return Py_True if this data-type descriptor - * has native byteorder if no fields are defined - * - * or if all sub-fields have native-byteorder if - * fields are defined - */ -static PyObject * -arraydescr_isnative_get(PyArray_Descr *self) -{ - PyObject *ret; - int retval; - retval = _arraydescr_isnative(self); - if (retval == -1) { - return NULL; - } - ret = retval ? Py_True : Py_False; - Py_INCREF(ret); - return ret; -} - -static PyObject * -arraydescr_fields_get(PyArray_Descr *self) -{ - if (self->names == NULL) { - Py_INCREF(Py_None); - return Py_None; - } - return PyDictProxy_New(self->fields); -} - -static PyObject * -arraydescr_hasobject_get(PyArray_Descr *self) -{ - PyObject *res; - if (PyDataType_FLAGCHK(self, NPY_ITEM_HASOBJECT)) { - res = Py_True; - } - else { - res = Py_False; - } - Py_INCREF(res); - return res; -} - -static PyObject * -arraydescr_names_get(PyArray_Descr *self) -{ - if (self->names == NULL) { - Py_INCREF(Py_None); - return Py_None; - } - Py_INCREF(self->names); - return self->names; -} - -static int -arraydescr_names_set(PyArray_Descr *self, PyObject *val) -{ - int N = 0; - int i; - PyObject *new_names; - if (self->names == NULL) { - PyErr_SetString(PyExc_ValueError, "there are no fields defined"); - return -1; - } - - N = PyTuple_GET_SIZE(self->names); - if (!PySequence_Check(val) || PyObject_Size((PyObject *)val) != N) { - PyErr_Format(PyExc_ValueError, "must replace all names at once" \ - " with a sequence of length %d", N); - return -1; - } - /* Make sure all entries are strings */ - for (i = 0; i < N; i++) { - PyObject *item; - int valid = 1; - item = PySequence_GetItem(val, i); - valid = PyString_Check(item); - Py_DECREF(item); - if (!valid) { - PyErr_Format(PyExc_ValueError, - "item #%d of names is of type %s and not string", - i, item->ob_type->tp_name); - return -1; - } - } - /* Update dictionary keys in fields */ - new_names = PySequence_Tuple(val); - for (i = 0; i < N; i++) { - PyObject *key; - PyObject *item; - PyObject *new_key; - key = PyTuple_GET_ITEM(self->names, i); - /* Borrowed reference to item */ - item = PyDict_GetItem(self->fields, key); - Py_INCREF(item); /* Hold on to it even through DelItem */ - new_key = PyTuple_GET_ITEM(new_names, i); - PyDict_DelItem(self->fields, key); - PyDict_SetItem(self->fields, new_key, item); - Py_DECREF(item); /* self->fields now holds reference */ - } - - /* Replace names */ - Py_DECREF(self->names); - self->names = new_names; - - return 0; -} - -static PyGetSetDef arraydescr_getsets[] = { - {"subdtype", - (getter)arraydescr_subdescr_get, - NULL, NULL, NULL}, - {"descr", - (getter)arraydescr_protocol_descr_get, - NULL, NULL, NULL}, - {"str", - (getter)arraydescr_protocol_typestr_get, - NULL, NULL, NULL}, - {"name", - (getter)arraydescr_typename_get, - NULL, NULL, NULL}, - {"base", - (getter)arraydescr_base_get, - NULL, NULL, NULL}, - {"shape", - (getter)arraydescr_shape_get, - NULL, NULL, NULL}, - {"isbuiltin", - (getter)arraydescr_isbuiltin_get, - NULL, NULL, NULL}, - {"isnative", - (getter)arraydescr_isnative_get, - NULL, NULL, NULL}, - {"fields", - (getter)arraydescr_fields_get, - NULL, NULL, NULL}, - {"names", - (getter)arraydescr_names_get, - (setter)arraydescr_names_set, - NULL, NULL}, - {"hasobject", - (getter)arraydescr_hasobject_get, - NULL, NULL, NULL}, - {NULL, NULL, NULL, NULL, NULL}, -}; - -static PyObject * -arraydescr_new(PyTypeObject *NPY_UNUSED(subtype), PyObject *args, PyObject *kwds) -{ - PyObject *odescr; - PyArray_Descr *descr, *conv; - Bool align = FALSE; - Bool copy = FALSE; - static char *kwlist[] = {"dtype", "align", "copy", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O&O&", - kwlist, &odescr, - PyArray_BoolConverter, &align, - PyArray_BoolConverter, ©)) { - return NULL; - } - if (align) { - if (!PyArray_DescrAlignConverter(odescr, &conv)) { - return NULL; - } - } - else if (!PyArray_DescrConverter(odescr, &conv)) { - return NULL; - } - /* Get a new copy of it unless it's already a copy */ - if (copy && conv->fields == Py_None) { - descr = PyArray_DescrNew(conv); - Py_DECREF(conv); - conv = descr; - } - return (PyObject *)conv; -} - - -/* return a tuple of (callable object, args, state). */ -static PyObject * -arraydescr_reduce(PyArray_Descr *self, PyObject *NPY_UNUSED(args)) -{ - /* - * version number of this pickle type. Increment if we need to - * change the format. Be sure to handle the old versions in - * arraydescr_setstate. - */ - const int version = 3; - PyObject *ret, *mod, *obj; - PyObject *state; - char endian; - int elsize, alignment; - - ret = PyTuple_New(3); - if (ret == NULL) { - return NULL; - } - mod = PyImport_ImportModule("numpy.core.multiarray"); - if (mod == NULL) { - Py_DECREF(ret); - return NULL; - } - obj = PyObject_GetAttrString(mod, "dtype"); - Py_DECREF(mod); - if (obj == NULL) { - Py_DECREF(ret); - return NULL; - } - PyTuple_SET_ITEM(ret, 0, obj); - if (PyTypeNum_ISUSERDEF(self->type_num) || - ((self->type_num == PyArray_VOID && - self->typeobj != &PyVoidArrType_Type))) { - obj = (PyObject *)self->typeobj; - Py_INCREF(obj); - } - else { - elsize = self->elsize; - if (self->type_num == PyArray_UNICODE) { - elsize >>= 2; - } - obj = PyString_FromFormat("%c%d",self->kind, elsize); - } - PyTuple_SET_ITEM(ret, 1, Py_BuildValue("(Nii)", obj, 0, 1)); - - /* - * Now return the state which is at least byteorder, - * subarray, and fields - */ - endian = self->byteorder; - if (endian == '=') { - endian = '<'; - if (!PyArray_IsNativeByteOrder(endian)) { - endian = '>'; - } - } - state = PyTuple_New(8); - PyTuple_SET_ITEM(state, 0, PyInt_FromLong(version)); - PyTuple_SET_ITEM(state, 1, PyString_FromFormat("%c", endian)); - PyTuple_SET_ITEM(state, 2, arraydescr_subdescr_get(self)); - if (self->names) { - Py_INCREF(self->names); - Py_INCREF(self->fields); - PyTuple_SET_ITEM(state, 3, self->names); - PyTuple_SET_ITEM(state, 4, self->fields); - } - else { - PyTuple_SET_ITEM(state, 3, Py_None); - PyTuple_SET_ITEM(state, 4, Py_None); - Py_INCREF(Py_None); - Py_INCREF(Py_None); - } - - /* for extended types it also includes elsize and alignment */ - if (PyTypeNum_ISEXTENDED(self->type_num)) { - elsize = self->elsize; - alignment = self->alignment; - } - else { - elsize = -1; - alignment = -1; - } - PyTuple_SET_ITEM(state, 5, PyInt_FromLong(elsize)); - PyTuple_SET_ITEM(state, 6, PyInt_FromLong(alignment)); - PyTuple_SET_ITEM(state, 7, PyInt_FromLong(self->hasobject)); - PyTuple_SET_ITEM(ret, 2, state); - return ret; -} - -/* returns 1 if this data-type has an object portion - used when setting the state because hasobject is not stored. -*/ -static int -_descr_find_object(PyArray_Descr *self) -{ - if (self->hasobject || self->type_num == PyArray_OBJECT || - self->kind == 'O') { - return NPY_OBJECT_DTYPE_FLAGS; - } - if (PyDescr_HASFIELDS(self)) { - PyObject *key, *value, *title = NULL; - PyArray_Descr *new; - int offset; - Py_ssize_t pos = 0; - - while (PyDict_Next(self->fields, &pos, &key, &value)) { - if NPY_TITLE_KEY(key, value) { - continue; - } - if (!PyArg_ParseTuple(value, "Oi|O", &new, &offset, &title)) { - PyErr_Clear(); - return 0; - } - if (_descr_find_object(new)) { - new->hasobject = NPY_OBJECT_DTYPE_FLAGS; - return NPY_OBJECT_DTYPE_FLAGS; - } - } - } - return 0; -} - -/* - * state is at least byteorder, subarray, and fields but could include elsize - * and alignment for EXTENDED arrays - */ -static PyObject * -arraydescr_setstate(PyArray_Descr *self, PyObject *args) -{ - int elsize = -1, alignment = -1; - int version = 3; - char endian; - PyObject *subarray, *fields, *names = NULL; - int incref_names = 1; - int dtypeflags = 0; - - if (self->fields == Py_None) { - Py_INCREF(Py_None); - return Py_None; - } - if (PyTuple_GET_SIZE(args) != 1 || - !(PyTuple_Check(PyTuple_GET_ITEM(args, 0)))) { - PyErr_BadInternalCall(); - return NULL; - } - switch (PyTuple_GET_SIZE(PyTuple_GET_ITEM(args,0))) { - case 8: - if (!PyArg_ParseTuple(args, "(icOOOiii)", &version, &endian, - &subarray, &names, &fields, &elsize, - &alignment, &dtypeflags)) { - return NULL; - } - break; - case 7: - if (!PyArg_ParseTuple(args, "(icOOOii)", &version, &endian, - &subarray, &names, &fields, &elsize, - &alignment)) { - return NULL; - } - break; - case 6: - if (!PyArg_ParseTuple(args, "(icOOii)", &version, - &endian, &subarray, &fields, - &elsize, &alignment)) { - PyErr_Clear(); - } - break; - case 5: - version = 0; - if (!PyArg_ParseTuple(args, "(cOOii)", - &endian, &subarray, &fields, &elsize, - &alignment)) { - return NULL; - } - break; - default: - /* raise an error */ - version = -1; - } - - /* - * If we ever need another pickle format, increment the version - * number. But we should still be able to handle the old versions. - */ - if (version < 0 || version > 3) { - PyErr_Format(PyExc_ValueError, - "can't handle version %d of numpy.dtype pickle", - version); - return NULL; - } - - if (version == 1 || version == 0) { - if (fields != Py_None) { - PyObject *key, *list; - key = PyInt_FromLong(-1); - list = PyDict_GetItem(fields, key); - if (!list) { - return NULL; - } - Py_INCREF(list); - names = list; - PyDict_DelItem(fields, key); - incref_names = 0; - } - else { - names = Py_None; - } - } - - - if ((fields == Py_None && names != Py_None) || - (names == Py_None && fields != Py_None)) { - PyErr_Format(PyExc_ValueError, - "inconsistent fields and names"); - return NULL; - } - - if (endian != '|' && PyArray_IsNativeByteOrder(endian)) { - endian = '='; - } - self->byteorder = endian; - if (self->subarray) { - Py_XDECREF(self->subarray->base); - Py_XDECREF(self->subarray->shape); - _pya_free(self->subarray); - } - self->subarray = NULL; - - if (subarray != Py_None) { - self->subarray = _pya_malloc(sizeof(PyArray_ArrayDescr)); - self->subarray->base = (PyArray_Descr *)PyTuple_GET_ITEM(subarray, 0); - Py_INCREF(self->subarray->base); - self->subarray->shape = PyTuple_GET_ITEM(subarray, 1); - Py_INCREF(self->subarray->shape); - } - - if (fields != Py_None) { - Py_XDECREF(self->fields); - self->fields = fields; - Py_INCREF(fields); - Py_XDECREF(self->names); - self->names = names; - if (incref_names) { - Py_INCREF(names); - } - } - - if (PyTypeNum_ISEXTENDED(self->type_num)) { - self->elsize = elsize; - self->alignment = alignment; - } - - self->hasobject = dtypeflags; - if (version < 3) { - self->hasobject = _descr_find_object(self); - } - Py_INCREF(Py_None); - return Py_None; -} - - - /*NUMPY_API - * returns a copy of the PyArray_Descr structure with the byteorder - * altered: - * no arguments: The byteorder is swapped (in all subfields as well) - * single argument: The byteorder is forced to the given state - * (in all subfields as well) - * - * Valid states: ('big', '>') or ('little' or '<') - * ('native', or '=') - * - * If a descr structure with | is encountered it's own - * byte-order is not changed but any fields are: - * - * - * Deep bytorder change of a data-type descriptor - * *** Leaves reference count of self unchanged --- does not DECREF self *** - */ -NPY_NO_EXPORT PyArray_Descr * -PyArray_DescrNewByteorder(PyArray_Descr *self, char newendian) -{ - PyArray_Descr *new; - char endian; - - new = PyArray_DescrNew(self); - endian = new->byteorder; - if (endian != PyArray_IGNORE) { - if (newendian == PyArray_SWAP) { - /* swap byteorder */ - if PyArray_ISNBO(endian) { - endian = PyArray_OPPBYTE; - } - else { - endian = PyArray_NATBYTE; - } - new->byteorder = endian; - } - else if (newendian != PyArray_IGNORE) { - new->byteorder = newendian; - } - } - if (new->names) { - PyObject *newfields; - PyObject *key, *value; - PyObject *newvalue; - PyObject *old; - PyArray_Descr *newdescr; - Py_ssize_t pos = 0; - int len, i; - - newfields = PyDict_New(); - /* make new dictionary with replaced PyArray_Descr Objects */ - while(PyDict_Next(self->fields, &pos, &key, &value)) { - if NPY_TITLE_KEY(key, value) { - continue; - } - if (!PyString_Check(key) || - !PyTuple_Check(value) || - ((len=PyTuple_GET_SIZE(value)) < 2)) { - continue; - } - old = PyTuple_GET_ITEM(value, 0); - if (!PyArray_DescrCheck(old)) { - continue; - } - newdescr = PyArray_DescrNewByteorder( - (PyArray_Descr *)old, newendian); - if (newdescr == NULL) { - Py_DECREF(newfields); Py_DECREF(new); - return NULL; - } - newvalue = PyTuple_New(len); - PyTuple_SET_ITEM(newvalue, 0, (PyObject *)newdescr); - for (i = 1; i < len; i++) { - old = PyTuple_GET_ITEM(value, i); - Py_INCREF(old); - PyTuple_SET_ITEM(newvalue, i, old); - } - PyDict_SetItem(newfields, key, newvalue); - Py_DECREF(newvalue); - } - Py_DECREF(new->fields); - new->fields = newfields; - } - if (new->subarray) { - Py_DECREF(new->subarray->base); - new->subarray->base = PyArray_DescrNewByteorder - (self->subarray->base, newendian); - } - return new; -} - - -static PyObject * -arraydescr_newbyteorder(PyArray_Descr *self, PyObject *args) -{ - char endian=PyArray_SWAP; - - if (!PyArg_ParseTuple(args, "|O&", PyArray_ByteorderConverter, - &endian)) { - return NULL; - } - return (PyObject *)PyArray_DescrNewByteorder(self, endian); -} - -static PyMethodDef arraydescr_methods[] = { - /* for pickling */ - {"__reduce__", - (PyCFunction)arraydescr_reduce, METH_VARARGS, NULL}, - {"__setstate__", - (PyCFunction)arraydescr_setstate, METH_VARARGS, NULL}, - {"newbyteorder", - (PyCFunction)arraydescr_newbyteorder, METH_VARARGS, NULL}, - {NULL, NULL, 0, NULL} /* sentinel */ -}; - -static PyObject * -arraydescr_str(PyArray_Descr *self) -{ - PyObject *sub; - - if (self->names) { - PyObject *lst; - lst = arraydescr_protocol_descr_get(self); - if (!lst) { - sub = PyString_FromString("<err>"); - PyErr_Clear(); - } - else { - sub = PyObject_Str(lst); - } - Py_XDECREF(lst); - if (self->type_num != PyArray_VOID) { - PyObject *p; - PyObject *t=PyString_FromString("'"); - p = arraydescr_protocol_typestr_get(self); - PyString_Concat(&p, t); - PyString_ConcatAndDel(&t, p); - p = PyString_FromString("("); - PyString_ConcatAndDel(&p, t); - PyString_ConcatAndDel(&p, PyString_FromString(", ")); - PyString_ConcatAndDel(&p, sub); - PyString_ConcatAndDel(&p, PyString_FromString(")")); - sub = p; - } - } - else if (self->subarray) { - PyObject *p; - PyObject *t = PyString_FromString("("); - PyObject *sh; - p = arraydescr_str(self->subarray->base); - if (!self->subarray->base->names && !self->subarray->base->subarray) { - PyObject *t=PyString_FromString("'"); - PyString_Concat(&p, t); - PyString_ConcatAndDel(&t, p); - p = t; - } - PyString_ConcatAndDel(&t, p); - PyString_ConcatAndDel(&t, PyString_FromString(",")); - if (!PyTuple_Check(self->subarray->shape)) { - sh = Py_BuildValue("(O)", self->subarray->shape); - } - else { - sh = self->subarray->shape; - Py_INCREF(sh); - } - PyString_ConcatAndDel(&t, PyObject_Str(sh)); - Py_DECREF(sh); - PyString_ConcatAndDel(&t, PyString_FromString(")")); - sub = t; - } - else if (PyDataType_ISFLEXIBLE(self) || !PyArray_ISNBO(self->byteorder)) { - sub = arraydescr_protocol_typestr_get(self); - } - else { - sub = arraydescr_typename_get(self); - } - return sub; -} - -static PyObject * -arraydescr_repr(PyArray_Descr *self) -{ - PyObject *sub, *s; - s = PyString_FromString("dtype("); - sub = arraydescr_str(self); - if (!self->names && !self->subarray) { - PyObject *t=PyString_FromString("'"); - PyString_Concat(&sub, t); - PyString_ConcatAndDel(&t, sub); - sub = t; - } - PyString_ConcatAndDel(&s, sub); - sub = PyString_FromString(")"); - PyString_ConcatAndDel(&s, sub); - return s; -} - -static PyObject * -arraydescr_richcompare(PyArray_Descr *self, PyObject *other, int cmp_op) -{ - PyArray_Descr *new = NULL; - PyObject *result = Py_NotImplemented; - if (!PyArray_DescrCheck(other)) { - if (PyArray_DescrConverter(other, &new) == PY_FAIL) { - return NULL; - } - } - else { - new = (PyArray_Descr *)other; - Py_INCREF(new); - } - switch (cmp_op) { - case Py_LT: - if (!PyArray_EquivTypes(self, new) && PyArray_CanCastTo(self, new)) { - result = Py_True; - } - else { - result = Py_False; - } - break; - case Py_LE: - if (PyArray_CanCastTo(self, new)) { - result = Py_True; - } - else { - result = Py_False; - } - break; - case Py_EQ: - if (PyArray_EquivTypes(self, new)) { - result = Py_True; - } - else { - result = Py_False; - } - break; - case Py_NE: - if (PyArray_EquivTypes(self, new)) - result = Py_False; - else - result = Py_True; - break; - case Py_GT: - if (!PyArray_EquivTypes(self, new) && PyArray_CanCastTo(new, self)) { - result = Py_True; - } - else { - result = Py_False; - } - break; - case Py_GE: - if (PyArray_CanCastTo(new, self)) { - result = Py_True; - } - else { - result = Py_False; - } - break; - default: - result = Py_NotImplemented; - } - - Py_XDECREF(new); - Py_INCREF(result); - return result; -} - -/************************************************************************* - **************** Implement Mapping Protocol *************************** - *************************************************************************/ - -static Py_ssize_t -descr_length(PyObject *self0) -{ - PyArray_Descr *self = (PyArray_Descr *)self0; - - if (self->names) { - return PyTuple_GET_SIZE(self->names); - } - else { - return 0; - } -} - -static PyObject * -descr_repeat(PyObject *self, Py_ssize_t length) -{ - PyObject *tup; - PyArray_Descr *new; - if (length < 0) { - return PyErr_Format(PyExc_ValueError, - "Array length must be >= 0, not %"INTP_FMT, - length); - } - tup = Py_BuildValue("O" NPY_SSIZE_T_PYFMT, self, length); - if (tup == NULL) { - return NULL; - } - PyArray_DescrConverter(tup, &new); - Py_DECREF(tup); - return (PyObject *)new; -} - -static PyObject * -descr_subscript(PyArray_Descr *self, PyObject *op) -{ - - if (self->names) { - if (PyString_Check(op) || PyUnicode_Check(op)) { - PyObject *obj = PyDict_GetItem(self->fields, op); - if (obj != NULL) { - PyObject *descr = PyTuple_GET_ITEM(obj, 0); - Py_INCREF(descr); - return descr; - } - else { - PyErr_Format(PyExc_KeyError, - "field named \'%s\' not found.", - PyString_AsString(op)); - } - } - else { - PyObject *name; - int value = PyArray_PyIntAsInt(op); - if (!PyErr_Occurred()) { - int size = PyTuple_GET_SIZE(self->names); - if (value < 0) { - value += size; - } - if (value < 0 || value >= size) { - PyErr_Format(PyExc_IndexError, - "0<=index<%d not %d", - size, value); - return NULL; - } - name = PyTuple_GET_ITEM(self->names, value); - return descr_subscript(self, name); - } - } - PyErr_SetString(PyExc_ValueError, - "only integers, strings or unicode values " - "allowed for getting fields."); - } - else { - PyObject *astr; - astr = arraydescr_str(self); - PyErr_Format(PyExc_KeyError, - "there are no fields in dtype %s.", - PyString_AsString(astr)); - Py_DECREF(astr); - } - return NULL; -} - -static PySequenceMethods descr_as_sequence = { - descr_length, - (binaryfunc)NULL, - descr_repeat, - NULL, NULL, - NULL, /* sq_ass_item */ - NULL, /* ssizessizeobjargproc sq_ass_slice */ - 0, /* sq_contains */ - 0, /* sq_inplace_concat */ - 0, /* sq_inplace_repeat */ -}; - -static PyMappingMethods descr_as_mapping = { - descr_length, /* mp_length*/ - (binaryfunc)descr_subscript, /* mp_subscript*/ - (objobjargproc)NULL, /* mp_ass_subscript*/ -}; - -/****************** End of Mapping Protocol ******************************/ - - -NPY_NO_EXPORT PyTypeObject PyArrayDescr_Type = { - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ - "numpy.dtype", /* tp_name */ - sizeof(PyArray_Descr), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)arraydescr_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - (reprfunc)arraydescr_repr, /* tp_repr */ - 0, /* tp_as_number */ - &descr_as_sequence, /* tp_as_sequence */ - &descr_as_mapping, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - (reprfunc)arraydescr_str, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - (richcmpfunc)arraydescr_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - arraydescr_methods, /* tp_methods */ - arraydescr_members, /* tp_members */ - arraydescr_getsets, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - arraydescr_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 -}; |