summaryrefslogtreecommitdiff
path: root/numpy/core
diff options
context:
space:
mode:
authorTravis Oliphant <oliphant@enthought.com>2006-06-14 01:34:36 +0000
committerTravis Oliphant <oliphant@enthought.com>2006-06-14 01:34:36 +0000
commit11869d369ab71f39d4a152260f88fae4df276378 (patch)
tree2379897f600da12a7f05a84e7bb703dfa04ed320 /numpy/core
parent6a4ff2dcd299ec2cc154726fbd04cad284edbb10 (diff)
downloadnumpy-11869d369ab71f39d4a152260f88fae4df276378.tar.gz
Compress Python-side array interface to __array_interface__ attribute.
Diffstat (limited to 'numpy/core')
-rw-r--r--numpy/core/defchararray.py2
-rw-r--r--numpy/core/include/numpy/arrayobject.h10
-rw-r--r--numpy/core/src/arrayobject.c254
3 files changed, 160 insertions, 106 deletions
diff --git a/numpy/core/defchararray.py b/numpy/core/defchararray.py
index f79389967..201a860cc 100644
--- a/numpy/core/defchararray.py
+++ b/numpy/core/defchararray.py
@@ -15,7 +15,7 @@ _unicode = unicode
class chararray(ndarray):
def __new__(subtype, shape, itemsize=1, unicode=False, buffer=None,
- offset=0, strides=None, order=None):
+ offset=0, strides=None, order='C'):
global _globalvar
if unicode:
diff --git a/numpy/core/include/numpy/arrayobject.h b/numpy/core/include/numpy/arrayobject.h
index ac8c391cb..d82fe0dda 100644
--- a/numpy/core/include/numpy/arrayobject.h
+++ b/numpy/core/include/numpy/arrayobject.h
@@ -1004,6 +1004,7 @@ typedef int (PyArray_FinalizeFunc)(PyArrayObject *, PyObject *);
#define OWNDATA 0x0004
#define OWN_DATA OWNDATA
+
/* An array never has the next four set; they're only used as parameter
flags to the the various FromAny functions */
@@ -1037,6 +1038,9 @@ typedef int (PyArray_FinalizeFunc)(PyArrayObject *, PyObject *);
*/
#define UPDATEIFCOPY 0x1000
+/* This flag is for the array interface */
+#define ARR_HAS_DESCR 0x0800
+
#define BEHAVED_FLAGS ALIGNED | WRITEABLE
#define BEHAVED_NS_FLAGS ALIGNED | WRITEABLE | NOTSWAPPED
@@ -1455,10 +1459,14 @@ typedef struct {
int flags; /* how should be data interpreted. Valid
flags are CONTIGUOUS (1), FORTRAN (2),
ALIGNED (0x100), NOTSWAPPED (0x200), and
- WRITEABLE (0x400)*/
+ WRITEABLE (0x400).
+ ARR_HAS_DESCR (0x800) states that arrdescr
+ field is present in structure */
intp *shape; /* A length-nd array of shape information */
intp *strides; /* A length-nd array of stride information */
void *data; /* A pointer to the first element of the array */
+ PyObject *descr; /* A list of fields or NULL (ignored if flags
+ does not have ARR_HAS_DESCR flag set) */
} PyArrayInterface;
/* Includes the "function" C-API -- these are all stored in a
diff --git a/numpy/core/src/arrayobject.c b/numpy/core/src/arrayobject.c
index 0b22ec510..b7015b1a3 100644
--- a/numpy/core/src/arrayobject.c
+++ b/numpy/core/src/arrayobject.c
@@ -5097,6 +5097,54 @@ array_strides_set(PyArrayObject *self, PyObject *obj)
}
+
+static PyObject *
+array_priority_get(PyArrayObject *self)
+{
+ if (PyArray_CheckExact(self))
+ return PyFloat_FromDouble(PyArray_PRIORITY);
+ else
+ return PyFloat_FromDouble(PyArray_SUBTYPE_PRIORITY);
+}
+
+static PyObject *arraydescr_protocol_typestr_get(PyArray_Descr *);
+
+static PyObject *
+array_typestr_get(PyArrayObject *self)
+{
+ return arraydescr_protocol_typestr_get(self->descr);
+}
+
+static PyObject *
+array_descr_get(PyArrayObject *self)
+{
+ Py_INCREF(self->descr);
+ return (PyObject *)self->descr;
+}
+
+static PyObject *arraydescr_protocol_descr_get(PyArray_Descr *self);
+
+static PyObject *
+array_protocol_descr_get(PyArrayObject *self)
+{
+ PyObject *res;
+ PyObject *dobj;
+
+ res = arraydescr_protocol_descr_get(self->descr);
+ if (res) return res;
+ PyErr_Clear();
+
+ /* get default */
+ dobj = PyTuple_New(2);
+ if (dobj == NULL) return NULL;
+ PyTuple_SET_ITEM(dobj, 0, PyString_FromString(""));
+ PyTuple_SET_ITEM(dobj, 1, array_typestr_get(self));
+ res = PyList_New(1);
+ if (res == NULL) {Py_DECREF(dobj); return NULL;}
+ PyList_SET_ITEM(res, 0, dobj);
+ return res;
+}
+
static PyObject *
array_protocol_strides_get(PyArrayObject *self)
{
@@ -5107,14 +5155,6 @@ array_protocol_strides_get(PyArrayObject *self)
return PyArray_IntTupleFromIntp(self->nd, self->strides);
}
-static PyObject *
-array_priority_get(PyArrayObject *self)
-{
- if (PyArray_CheckExact(self))
- return PyFloat_FromDouble(PyArray_PRIORITY);
- else
- return PyFloat_FromDouble(PyArray_SUBTYPE_PRIORITY);
-}
static PyObject *
@@ -5123,7 +5163,45 @@ array_dataptr_get(PyArrayObject *self)
return Py_BuildValue("NO",
PyString_FromFormat("%p", self->data),
(self->flags & WRITEABLE ? Py_False :
- Py_True));
+ Py_True));
+}
+
+static PyObject *
+array_interface_get(PyArrayObject *self)
+{
+ PyObject *dict;
+ PyObject *obj;
+ dict = PyDict_New();
+ if (dict == NULL) return NULL;
+ /* dataptr
+ typestr
+ descr
+ shape
+ strides
+ */
+
+ /* dataptr */
+ obj = array_dataptr_get(self);
+ PyDict_SetItemString(dict, "data", obj);
+ Py_DECREF(obj);
+
+ obj = array_protocol_strides_get(self);
+ PyDict_SetItemString(dict, "strides", obj);
+ Py_DECREF(obj);
+
+ obj = array_protocol_descr_get(self);
+ PyDict_SetItemString(dict, "descr", obj);
+ Py_DECREF(obj);
+
+ obj = arraydescr_protocol_typestr_get(self->descr);
+ PyDict_SetItemString(dict, "typestr", obj);
+ Py_DECREF(obj);
+
+ obj = array_shape_get(self);
+ PyDict_SetItemString(dict, "shape", obj);
+ Py_DECREF(obj);
+
+ return dict;
}
static PyObject *
@@ -5226,22 +5304,6 @@ array_nbytes_get(PyArrayObject *self)
}
-static PyObject *arraydescr_protocol_typestr_get(PyArray_Descr *);
-
-static PyObject *
-array_typestr_get(PyArrayObject *self)
-{
- return arraydescr_protocol_typestr_get(self->descr);
-}
-
-static PyObject *
-array_descr_get(PyArrayObject *self)
-{
- Py_INCREF(self->descr);
- return (PyObject *)self->descr;
-}
-
-
/* If the type is changed.
Also needing change: strides, itemsize
@@ -5343,27 +5405,6 @@ array_descr_set(PyArrayObject *self, PyObject *arg)
}
static PyObject *
-array_protocol_descr_get(PyArrayObject *self)
-{
- PyObject *res;
- PyObject *dobj;
-
- res = PyObject_GetAttrString((PyObject *)self->descr, "descr");
- if (res) return res;
- PyErr_Clear();
-
- /* get default */
- dobj = PyTuple_New(2);
- if (dobj == NULL) return NULL;
- PyTuple_SET_ITEM(dobj, 0, PyString_FromString(""));
- PyTuple_SET_ITEM(dobj, 1, array_typestr_get(self));
- res = PyList_New(1);
- if (res == NULL) {Py_DECREF(dobj); return NULL;}
- PyList_SET_ITEM(res, 0, dobj);
- return res;
-}
-
-static PyObject *
array_struct_get(PyArrayObject *self)
{
PyArrayInterface *inter;
@@ -5380,6 +5421,11 @@ array_struct_get(PyArrayObject *self)
inter->strides = self->strides;
inter->shape = self->dimensions;
inter->data = self->data;
+ if (self->descr->fields && self->descr->fields != Py_None) {
+ inter->descr = arraydescr_protocol_descr_get(self->descr);
+ if (inter->descr == NULL) PyErr_Clear();
+ else inter->flags &= ARR_HAS_DESCR;
+ }
Py_INCREF(self);
return PyCObject_FromVoidPtrAndDesc(inter, self, gentype_struct_free);
}
@@ -5667,30 +5713,14 @@ static PyGetSetDef array_getsetlist[] = {
(getter)array_flat_get,
(setter)array_flat_set,
"a 1-d view of a contiguous array"},
- {"__array_data__",
- (getter)array_dataptr_get,
- NULL,
- "Array protocol: data"},
- {"__array_typestr__",
- (getter)array_typestr_get,
- NULL,
- "Array protocol: typestr"},
- {"__array_descr__",
- (getter)array_protocol_descr_get,
+ {"__array_interface__",
+ (getter)array_interface_get,
NULL,
- "Array protocol: descr"},
- {"__array_shape__",
- (getter)array_shape_get,
- NULL,
- "Array protocol: shape"},
- {"__array_strides__",
- (getter)array_protocol_strides_get,
- NULL,
- "Array protocol: strides"},
+ "Array protocol: Python side"},
{"__array_struct__",
(getter)array_struct_get,
NULL,
- "Array protocol: struct"},
+ "Array protocol: C-struct side"},
{"__array_priority__",
(getter)array_priority_get,
NULL,
@@ -5724,10 +5754,10 @@ static char Arraytype__doc__[] =
" command. Arrays are sequence, mapping and numeric objects.\n"
" More information is available in the numpy module and by looking\n"
" at the methods and attributes of an array.\n\n"
- " ndarray.__new__(subtype, shape=, dtype=int_, buffer=None, \n"
- " offset=0, strides=None, fortran=False)\n\n"
+ " ndarray.__new__(subtype, shape=, dtype=int, buffer=None, \n"
+ " offset=0, strides=None, order=None)\n\n"
" There are two modes of creating an array using __new__:\n"
- " 1) If buffer is None, then only shape, dtype, and fortran \n"
+ " 1) If buffer is None, then only shape, dtype, and order \n"
" are used\n"
" 2) If buffer is an object exporting the buffer interface, then\n"
" all keywords are interpreted.\n"
@@ -5817,14 +5847,32 @@ discover_depth(PyObject *s, int max, int stop_at_string, int stop_at_tuple)
if(PyString_Check(s) || PyBuffer_Check(s) || PyUnicode_Check(s))
return stop_at_string ? 0:1;
if (stop_at_tuple && PyTuple_Check(s)) return 0;
- if ((e=PyObject_GetAttrString(s, "__array_shape__")) != NULL) {
- if (PyTuple_Check(e)) d=PyTuple_GET_SIZE(e);
- else d=-1;
+ if ((e=PyObject_GetAttrString(s, "__array_interface__")) != NULL) {
+ d = -1;
+ if (PyDict_Check(e)) {
+ PyObject *new;
+ new = PyDict_GetItemString(e, "shape");
+ if (new && PyTuple_Check(new))
+ d = PyTuple_GET_SIZE(new);
+ }
Py_DECREF(e);
if (d>-1) return d;
}
else PyErr_Clear();
-
+ if ((e=PyObject_GetAttrString(s, "__array_struct__")) != NULL) {
+ d = -1;
+ if (PyCObject_Check(e)) {
+ PyArrayInterface *inter;
+ inter = (PyArrayInterface *)PyCObject_AsVoidPtr(e);
+ if (inter->version == 2) {
+ d = inter->nd;
+ }
+ }
+ Py_DECREF(e);
+ if (d > -1) return d;
+ }
+ else PyErr_Clear();
+
if (PySequence_Length(s) == 0)
return 1;
if ((e=PySequence_GetItem(s,0)) == NULL) return -1;
@@ -5997,9 +6045,14 @@ _array_find_type(PyObject *op, PyArray_Descr *minitype, int max)
goto finish;
}
- if ((ip=PyObject_GetAttrString(op, "__array_typestr__"))!=NULL) {
- if (PyString_Check(ip)) {
- chktype =_array_typedescr_fromstr(PyString_AS_STRING(ip));
+ 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;
@@ -6803,6 +6856,7 @@ PyArray_FromInterface(PyObject *input)
{
PyObject *attr=NULL, *item=NULL;
PyObject *tstr=NULL, *shape=NULL;
+ PyObject *inter=NULL;
PyArrayObject *ret;
PyArray_Descr *type=NULL;
char *data;
@@ -6816,12 +6870,16 @@ PyArray_FromInterface(PyObject *input)
/* Get the typestring -- ignore array_descr */
/* Get the strides */
- shape = PyObject_GetAttrString(input, "__array_shape__");
- if (shape == NULL) {PyErr_Clear(); return Py_NotImplemented;}
- tstr = PyObject_GetAttrString(input, "__array_typestr__");
- if (tstr == NULL) {Py_DECREF(shape); PyErr_Clear(); return Py_NotImplemented;}
+ inter = PyObject_GetAttrString(input, "__array_interface__");
+ if (inter == NULL) {PyErr_Clear(); return Py_NotImplemented;}
+ if (!PyDict_Check(inter)) {Py_DECREF(inter); return Py_NotImplemented;}
- attr = PyObject_GetAttrString(input, "__array_data__");
+ shape = PyDict_GetItemString(inter, "shape");
+ if (shape == NULL) {Py_DECREF(inter); return Py_NotImplemented;}
+ tstr = PyDict_GetItemString(inter, "typestr");
+ if (tstr == NULL) {Py_DECREF(inter); return Py_NotImplemented;}
+
+ attr = PyDict_GetItemString(inter, "data");
if ((attr == NULL) || (attr==Py_None) || (!PyTuple_Check(attr))) {
if (attr && (attr != Py_None)) item=attr;
else item=input;
@@ -6834,24 +6892,22 @@ PyArray_FromInterface(PyObject *input)
if (res < 0) goto fail;
dataflags &= ~WRITEABLE;
}
- Py_XDECREF(attr);
- attr = PyObject_GetAttrString(input, "__array_offset__");
+ attr = PyDict_GetItemString(inter, "offset");
if (attr) {
long num = PyInt_AsLong(attr);
if (error_converting(num)) {
PyErr_SetString(PyExc_TypeError,
- "__array_offset__ "\
+ "offset "\
"must be an integer");
goto fail;
}
data += num;
}
- else PyErr_Clear();
}
else {
if (PyTuple_GET_SIZE(attr) != 2) {
PyErr_SetString(PyExc_TypeError,
- "__array_data__ must return " \
+ "data must return " \
"a 2-tuple with ('data pointer "\
"string', read-only flag)");
goto fail;
@@ -6860,7 +6916,7 @@ PyArray_FromInterface(PyObject *input)
"%p", (void **)&data);
if (res < 1) {
PyErr_SetString(PyExc_TypeError,
- "__array_data__ string cannot be " \
+ "data string cannot be " \
"converted");
goto fail;
}
@@ -6868,20 +6924,16 @@ PyArray_FromInterface(PyObject *input)
dataflags &= ~WRITEABLE;
}
}
- Py_XDECREF(attr);
attr = tstr;
if (!PyString_Check(attr)) {
- PyErr_SetString(PyExc_TypeError, "__array_typestr__ must be a string");
- Py_INCREF(attr); /* decref'd twice below */
+ PyErr_SetString(PyExc_TypeError, "typestr must be a string");
goto fail;
}
type = _array_typedescr_fromstr(PyString_AS_STRING(attr));
- Py_DECREF(attr); attr=NULL; tstr=NULL;
if (type==NULL) goto fail;
attr = shape;
if (!PyTuple_Check(attr)) {
- PyErr_SetString(PyExc_TypeError, "__array_shape__ must be a tuple");
- Py_INCREF(attr); /* decref'd twice below */
+ PyErr_SetString(PyExc_TypeError, "shape must be a tuple");
Py_DECREF(type);
goto fail;
}
@@ -6891,7 +6943,6 @@ PyArray_FromInterface(PyObject *input)
dims[i] = PyArray_PyIntAsIntp(item);
if (error_converting(dims[i])) break;
}
- Py_DECREF(attr); shape=NULL;
ret = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type, type,
n, dims,
@@ -6901,21 +6952,18 @@ PyArray_FromInterface(PyObject *input)
Py_INCREF(input);
ret->base = input;
- attr = PyObject_GetAttrString(input, "__array_strides__");
+ attr = PyDict_GetItemString(inter, "strides");
if (attr != NULL && attr != Py_None) {
if (!PyTuple_Check(attr)) {
PyErr_SetString(PyExc_TypeError,
- "__array_strides__ must be a tuple");
- Py_DECREF(attr);
+ "strides must be a tuple");
Py_DECREF(ret);
return NULL;
}
if (n != PyTuple_GET_SIZE(attr)) {
PyErr_SetString(PyExc_ValueError,
"mismatch in length of "\
- "__array_strides__ and "\
- "__array_shape__");
- Py_DECREF(attr);
+ "strides and shape");
Py_DECREF(ret);
return NULL;
}
@@ -6924,18 +6972,16 @@ PyArray_FromInterface(PyObject *input)
strides[i] = PyArray_PyIntAsIntp(item);
if (error_converting(strides[i])) break;
}
- Py_DECREF(attr);
if (PyErr_Occurred()) PyErr_Clear();
memcpy(ret->strides, strides, n*sizeof(intp));
}
else PyErr_Clear();
PyArray_UpdateFlags(ret, UPDATE_ALL_FLAGS);
+ Py_DECREF(inter);
return (PyObject *)ret;
fail:
- Py_XDECREF(attr);
- Py_XDECREF(shape);
- Py_XDECREF(tstr);
+ Py_XDECREF(inter);
return NULL;
}