diff options
author | Travis Oliphant <oliphant@enthought.com> | 2006-03-15 00:48:04 +0000 |
---|---|---|
committer | Travis Oliphant <oliphant@enthought.com> | 2006-03-15 00:48:04 +0000 |
commit | 03736884e2fb993e096ef801dd49135b9292b823 (patch) | |
tree | 5556dc46592b881b33ae600e385c8578e3e4ebb6 /numpy/core/src/arrayobject.c | |
parent | 440214d5835da50d9dad3103835fb8b3967eb3b5 (diff) | |
download | numpy-03736884e2fb993e096ef801dd49135b9292b823.tar.gz |
Changed the C-API by making the a.flags object a builtin object for speed. Also fixed issues with linalg and matrices.
Diffstat (limited to 'numpy/core/src/arrayobject.c')
-rw-r--r-- | numpy/core/src/arrayobject.c | 388 |
1 files changed, 385 insertions, 3 deletions
diff --git a/numpy/core/src/arrayobject.c b/numpy/core/src/arrayobject.c index aa3d112ce..9590996e4 100644 --- a/numpy/core/src/arrayobject.c +++ b/numpy/core/src/arrayobject.c @@ -4434,8 +4434,7 @@ array_ndim_get(PyArrayObject *self) static PyObject * array_flags_get(PyArrayObject *self) { - return PyObject_CallMethod(_numpy_internal, "flagsobj", "Oii", - self, self->flags, 0); + return PyArray_NewFlagsObject((PyObject *)self); } static PyObject * @@ -8414,7 +8413,7 @@ arraydescr_dealloc(PyArray_Descr *self) Py_DECREF(self->subarray->base); _pya_free(self->subarray); } - self->ob_type->tp_free(self); + self->ob_type->tp_free((PyObject *)self); } /* we need to be careful about setting attributes because these @@ -9081,3 +9080,386 @@ static PyTypeObject PyArrayDescr_Type = { 0, /* tp_subclasses */ 0 /* tp_weaklist */ }; + + +/** Array Flags Object **/ + +typedef struct PyArrayFlagsObject { + PyObject_HEAD + PyObject *arr; + int flags; +} PyArrayFlagsObject; + +/*OBJECT_API + Get New ArrayFlagsObject +*/ +static PyObject * +PyArray_NewFlagsObject(PyObject *obj) +{ + PyObject *flagobj; + int flags; + if (obj == NULL) { + flags = CONTIGUOUS | OWNDATA | FORTRAN | ALIGNED; + } + else { + flags = PyArray_FLAGS(obj); + } + flagobj = PyArrayFlags_Type.tp_alloc(&PyArrayFlags_Type, 0); + if (flagobj == NULL) return NULL; + Py_XINCREF(obj); + ((PyArrayFlagsObject *)flagobj)->arr = obj; + ((PyArrayFlagsObject *)flagobj)->flags = flags; + + return flagobj; +} + +static void +arrayflags_dealloc(PyArrayFlagsObject *self) +{ + Py_XDECREF(self->arr); + self->ob_type->tp_free((PyObject *)self); +} + + +#define _define_get(UPPER, lower) \ +static PyObject * \ +arrayflags_ ## lower ## _get(PyArrayFlagsObject *self) \ +{ \ + PyObject *item; \ + item = ((self->flags & (UPPER)) == (UPPER)) ? Py_True : Py_False; \ + Py_INCREF(item); \ + return item; \ +} + +_define_get(CONTIGUOUS, contiguous) +_define_get(FORTRAN, fortran) +_define_get(UPDATEIFCOPY, updateifcopy) +_define_get(OWNDATA, owndata) +_define_get(ALIGNED, aligned) +_define_get(WRITEABLE, writeable) + +_define_get(ALIGNED|WRITEABLE, behaved) +_define_get(ALIGNED|WRITEABLE|CONTIGUOUS, carray) + +static PyObject * +arrayflags_forc_get(PyArrayFlagsObject *self) +{ + PyObject *item; + + if (((self->flags & FORTRAN) == FORTRAN) || + ((self->flags & CONTIGUOUS) == CONTIGUOUS)) + item = Py_True; + else + item = Py_False; + + Py_INCREF(item); + return item; +} + +static PyObject * +arrayflags_fnc_get(PyArrayFlagsObject *self) +{ + PyObject *item; + + if (((self->flags & FORTRAN) == FORTRAN) && + !((self->flags & CONTIGUOUS) == CONTIGUOUS)) + item = Py_True; + else + item = Py_False; + + Py_INCREF(item); + return item; +} + +static PyObject * +arrayflags_farray_get(PyArrayFlagsObject *self) +{ + PyObject *item; + + if (((self->flags & (ALIGNED|WRITEABLE|FORTRAN)) == \ + (ALIGNED|WRITEABLE|FORTRAN)) && + !((self->flags & CONTIGUOUS) == CONTIGUOUS)) + item = Py_True; + else + item = Py_False; + + Py_INCREF(item); + return item; +} + +static PyObject * +arrayflags_num_get(PyArrayFlagsObject *self) +{ + return PyInt_FromLong(self->flags); +} + +/* relies on setflags order being write, align, uic */ +static int +arrayflags_updateifcopy_set(PyArrayFlagsObject *self, PyObject *obj) +{ + PyObject *res; + if (self->arr == NULL) { + PyErr_SetString(PyExc_ValueError, "Cannot set flags on array scalars."); + return -1; + } + res = PyObject_CallMethod(self->arr, "setflags", "OOO", Py_None, Py_None, + (PyObject_IsTrue(obj) ? Py_True : Py_False)); + if (res == NULL) return -1; + Py_DECREF(res); + return 0; +} + +static int +arrayflags_aligned_set(PyArrayFlagsObject *self, PyObject *obj) +{ + PyObject *res; + if (self->arr == NULL) { + PyErr_SetString(PyExc_ValueError, "Cannot set flags on array scalars."); + return -1; + } + res = PyObject_CallMethod(self->arr, "setflags", "OOO", Py_None, + (PyObject_IsTrue(obj) ? Py_True : Py_False), + Py_None); + if (res == NULL) return -1; + Py_DECREF(res); + return 0; +} + +static int +arrayflags_writeable_set(PyArrayFlagsObject *self, PyObject *obj) +{ + PyObject *res; + if (self->arr == NULL) { + PyErr_SetString(PyExc_ValueError, "Cannot set flags on array scalars."); + return -1; + } + res = PyObject_CallMethod(self->arr, "setflags", "OOO", + (PyObject_IsTrue(obj) ? Py_True : Py_False), + Py_None, Py_None); + if (res == NULL) return -1; + Py_DECREF(res); + return 0; +} + + +static PyGetSetDef arrayflags_getsets[] = { + {"contiguous", + (getter)arrayflags_contiguous_get, + NULL, + ""}, + {"fortran", + (getter)arrayflags_fortran_get, + NULL, + ""}, + {"updateifcopy", + (getter)arrayflags_updateifcopy_get, + (setter)arrayflags_updateifcopy_set, + ""}, + {"owndata", + (getter)arrayflags_owndata_get, + NULL, + ""}, + {"aligned", + (getter)arrayflags_aligned_get, + (setter)arrayflags_aligned_set, + ""}, + {"writeable", + (getter)arrayflags_writeable_get, + (setter)arrayflags_writeable_set, + ""}, + {"fnc", + (getter)arrayflags_fnc_get, + NULL, + ""}, + {"forc", + (getter)arrayflags_forc_get, + NULL, + ""}, + {"behaved", + (getter)arrayflags_behaved_get, + NULL, + ""}, + {"carray", + (getter)arrayflags_carray_get, + NULL, + ""}, + {"farray", + (getter)arrayflags_farray_get, + NULL, + ""}, + {"num", + (getter)arrayflags_num_get, + NULL, + ""}, + {NULL, NULL, NULL, NULL}, +}; + +static PyObject * +arrayflags_getitem(PyArrayFlagsObject *self, PyObject *ind) +{ + char *key; + int n; + if (!PyString_Check(ind)) goto fail; + key = PyString_AS_STRING(ind); + n = PyString_GET_SIZE(ind); + if ((strncmp(key,"CONTIGUOUS",n)==0) || + (strncmp(key,"C",n))) + return arrayflags_contiguous_get(self); + else if ((strncmp(key, "FORTRAN", n)==0) || + (strncmp(key, "F", n)==0)) + return arrayflags_fortran_get(self); + else if ((strncmp(key, "WRITEABLE", n)==0) || + (strncmp(key, "W", n)==0)) + return arrayflags_writeable_get(self); + else if ((strncmp(key, "BEHAVED", n)==0) || + (strncmp(key, "B", n)==0)) + return arrayflags_behaved_get(self); + else if ((strncmp(key, "OWNDATA", n)==0) || + (strncmp(key, "O", n)==0)) + return arrayflags_owndata_get(self); + else if ((strncmp(key, "ALIGNED", n)==0) || + (strncmp(key, "A", n)==0)) + return arrayflags_aligned_get(self); + else if ((strncmp(key, "UPDATEIFCOPY", n)==0) || + (strncmp(key, "U", n)==0)) + return arrayflags_updateifcopy_get(self); + else if ((strncmp(key, "FNC", n)==0)) + return arrayflags_fnc_get(self); + else if ((strncmp(key, "FORC", n)==0)) + return arrayflags_forc_get(self); + else if ((strncmp(key, "CARRAY", n)==0) || + (strncmp(key, "CA", n)==0)) + return arrayflags_carray_get(self); + else if ((strncmp(key, "FARRAY", n)==0) || + (strncmp(key, "FA", n)==0)) + return arrayflags_farray_get(self); + else goto fail; + + fail: + PyErr_SetString(PyExc_KeyError, "Unknown flag"); + return NULL; +} + +static int +arrayflags_setitem(PyArrayFlagsObject *self, PyObject *ind, PyObject *item) +{ + char *key; + int n; + if (!PyString_Check(ind)) goto fail; + key = PyString_AS_STRING(ind); + n = PyString_GET_SIZE(ind); + if ((strncmp(key, "WRITEABLE", n)==0) || + (strncmp(key, "W", n)==0)) + return arrayflags_writeable_set(self, item); + else if ((strncmp(key, "ALIGNED", n)==0) || + (strncmp(key, "A", n)==0)) + return arrayflags_aligned_set(self, item); + else if ((strncmp(key, "UPDATEIFCOPY", n)==0) || + (strncmp(key, "U", n)==0)) + return arrayflags_updateifcopy_set(self, item); + else goto fail; + return 0; + +fail: + PyErr_SetString(PyExc_KeyError, "Unknown flag"); + return -1; +} + +static char * +_torf_(int flags, int val) +{ + if ((flags & val) == val) return "True"; + else return "False"; +} + +static PyObject * +arrayflags_print(PyArrayFlagsObject *self) +{ + int fl = self->flags; + + return PyString_FromFormat(" %s : %s\n %s : %s\n %s : %s\n"\ + " %s : %s\n %s : %s\n %s : %s", + "CONTIGUOUS", _torf_(fl, CONTIGUOUS), + "FORTRAN", _torf_(fl, FORTRAN), + "OWNDATA", _torf_(fl, OWNDATA), + "WRITEABLE", _torf_(fl, WRITEABLE), + "ALIGNED", _torf_(fl, ALIGNED), + "UPDATEIFCOPY", _torf_(fl, UPDATEIFCOPY)); +} + + +static PyMappingMethods arrayflags_as_mapping = { +#if PY_VERSION_HEX >= 0x02050000 + (lenfunc)NULL, /*mp_length*/ +#else + (inquiry)NULL, /*mp_length*/ +#endif + (binaryfunc)arrayflags_getitem, /*mp_subscript*/ + (objobjargproc)arrayflags_setitem, /*mp_ass_subscript*/ +}; + + +static PyObject * +arrayflags_new(PyTypeObject *self, PyObject *args, PyObject *kwds) +{ + PyObject *arg=NULL; + if (!PyArg_UnpackTuple(args, "flagsobj", 0, 1, &arg)) + return NULL; + + if ((arg != NULL) && PyArray_Check(arg)) { + return PyArray_NewFlagsObject(arg); + } + else { + return PyArray_NewFlagsObject(NULL); + } +} + +static PyTypeObject PyArrayFlags_Type = { + PyObject_HEAD_INIT(NULL) + 0, + "numpy.flagsobj", + sizeof(PyArrayFlagsObject), + 0, /* tp_itemsize */ + /* methods */ + (destructor)arrayflags_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + (reprfunc)arrayflags_print, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + &arrayflags_as_mapping, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + (reprfunc)arrayflags_print, /* 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 */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + arrayflags_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 */ + arrayflags_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 */ +}; |