[Numpy-svn] r3411 - in trunk/numpy/core: include/numpy src

numpy-svn at scipy.org numpy-svn at scipy.org
Sat Oct 28 04:18:09 CDT 2006


Author: oliphant
Date: 2006-10-28 04:18:00 -0500 (Sat, 28 Oct 2006)
New Revision: 3411

Modified:
   trunk/numpy/core/include/numpy/ndarrayobject.h
   trunk/numpy/core/src/arraymethods.c
   trunk/numpy/core/src/arrayobject.c
   trunk/numpy/core/src/arraytypes.inc.src
   trunk/numpy/core/src/multiarraymodule.c
Log:
Expand usage of hasobject to be a flag-like entity keeping track of how the data-type should be used.

Modified: trunk/numpy/core/include/numpy/ndarrayobject.h
===================================================================
--- trunk/numpy/core/include/numpy/ndarrayobject.h	2006-10-27 21:42:27 UTC (rev 3410)
+++ trunk/numpy/core/include/numpy/ndarrayobject.h	2006-10-28 09:18:00 UTC (rev 3411)
@@ -1105,14 +1105,40 @@
         int **cancastscalarkindto;
         int *cancastto;
 
-        /* Set to 1 if you want pickles of this type
-           to go out as lists of _getitem objects
-        */
-        int listpickle;
+        int listpickle;           /* Unused */
 
 } PyArray_ArrFuncs;
 
+#define NPY_ITEM_REFCOUNT   0x01  /* The item must be reference counted
+                                     when it is inserted or extracted. */
+#define NPY_ITEM_HASOBJECT  0x01  /* Same as needing REFCOUNT */
 
+#define NPY_LIST_PICKLE     0x02  /* Convert to list for pickling */
+#define NPY_ITEM_IS_POINTER 0x06  /* The item is a POINTER -- automatic
+                                     LIST_PICKLE       */
+
+#define NPY_NEEDS_INIT      0x08  /* memory needs to be initialized 
+                                     for this data-type */
+
+#define NPY_NEEDS_PYAPI     0x10  /* operations need Python C-API 
+                                     so don't give-up thread. */
+
+#define NPY_USE_GETITEM     0x20  /* Use f.getitem when extracting elements 
+                                     of this data-type */
+
+
+/* These are inherited for global data-type if any data-types in the field 
+   have them */
+#define NPY_FROM_FIELDS     (NPY_NEEDS_INIT | NPY_LIST_PICKLE | NPY_ITEM_REFCOUNT | NPY_NEEDS_PYAPI)
+                                     
+#define NPY_OBJECT_DTYPE_FLAGS (NPY_LIST_PICKLE | NPY_USE_GETITEM | NPY_ITEM_IS_POINTER | NPY_ITEM_REFCOUNT | NPY_NEEDS_INIT | NPY_NEEDS_PYAPI)
+
+#define PyDataType_FLAGCHK(dtype, flag) \
+        ((dtype->hasobject & flag) == flag)
+#define PyDataType_REFCHK(dtype) \
+        PyDataType_FLAGCHK(dtype, NPY_ITEM_REFCOUNT)
+
+/* Change dtype hasobject to 32-bit in 1.1 and change its name */
 typedef struct {
         PyObject_HEAD
         PyTypeObject *typeobj;  /* the type object representing an
@@ -1123,7 +1149,8 @@
         char type;              /* unique-character representing this type */
         char byteorder;         /* '>' (big), '<' (little), '|'
                                    (not-applicable), or '=' (native). */
-        char hasobject;        /* non-zero if it has object arrays in fields */
+        char hasobject;         /* non-zero if it has object arrays 
+                                   in fields */
         int type_num;          /* number representing this type */
         int elsize;             /* element size for this type */
         int alignment;          /* alignment needed for this type */
@@ -1294,8 +1321,12 @@
 #define NPY_BEGIN_THREADS_DEF PyThreadState *_save=NULL;
 #define NPY_BEGIN_THREADS _save = PyEval_SaveThread();
 #define NPY_END_THREADS   if (_save) PyEval_RestoreThread(_save);
-#define NPY_BEGIN_THREADS_DESCR(dtype) if (!((dtype)->hasobject)) NPY_BEGIN_THREADS
-#define NPY_END_THREADS_DESCR(dtype) if (!((dtype)->hasobject)) NPY_END_THREADS
+#define NPY_BEGIN_THREADS_DESCR(dtype)                          \
+        if (!(PyDataType_FLAGCHK(dtype, NPY_NEEDS_PYAPI)))      \
+                NPY_BEGIN_THREADS
+#define NPY_END_THREADS_DESCR(dtype)                            \
+        if (!(PyDataType_FLAGCHK(dtype, NPY_NEEDS_PYAPI)))      \
+                NPY_END_THREADS
 #define NPY_ALLOW_C_API_DEF  PyGILState_STATE __save__;
 #define NPY_ALLOW_C_API      __save__ = PyGILState_Ensure();
 #define NPY_DISABLE_C_API    PyGILState_Release(__save__);

Modified: trunk/numpy/core/src/arraymethods.c
===================================================================
--- trunk/numpy/core/src/arraymethods.c	2006-10-27 21:42:27 UTC (rev 3410)
+++ trunk/numpy/core/src/arraymethods.c	2006-10-28 09:18:00 UTC (rev 3411)
@@ -897,8 +897,20 @@
 _deepcopy_call(char *iptr, char *optr, PyArray_Descr *dtype,
 	       PyObject *deepcopy, PyObject *visit)
 {
-	if (dtype->hasobject == 0) return;
-	if (dtype->type_num == PyArray_OBJECT) {
+	if (!PyDataType_REFCHK(dtype)) return;
+	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 (!PyArg_ParseTuple(value, "Oi|O", &new, &offset,
+					      &title)) return;
+                        _deepcopy_call(iptr + offset, optr + offset, new,
+				       deepcopy, visit);
+                }
+        }
+        else {
 		PyObject **itemp, **otemp;
 		PyObject *res;
 		itemp = (PyObject **)iptr;
@@ -911,18 +923,7 @@
 		Py_XDECREF(*otemp);
 		*otemp = res;
 	}
-	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 (!PyArg_ParseTuple(value, "Oi|O", &new, &offset,
-					      &title)) return;
-                        _deepcopy_call(iptr + offset, optr + offset, new,
-				       deepcopy, visit);
-                }
-        }
+
 }
 
 
@@ -936,7 +937,7 @@
 
         if (!PyArg_ParseTuple(args, "O", &visit)) return NULL;
         ret = PyArray_Copy(self);
-        if (self->descr->hasobject) {
+        if (PyDataType_REFCHK(self->descr)) {
                 copy = PyImport_ImportModule("copy");
                 if (copy == NULL) return NULL;
                 deepcopy = PyObject_GetAttrString(copy, "deepcopy");
@@ -1057,7 +1058,7 @@
 	mybool = (PyArray_ISFORTRAN(self) ? Py_True : Py_False);
 	Py_INCREF(mybool);
 	PyTuple_SET_ITEM(state, 3, mybool);
-	if (self->descr->hasobject || self->descr->f->listpickle) {
+	if (PyDataType_FLAGCHK(self->descr, NPY_LIST_PICKLE)) {
 		thestr = _getlist_pkl(self);
 	}
 	else {
@@ -1134,7 +1135,7 @@
 		return NULL;
 	}
 
-	if (typecode->hasobject || typecode->f->listpickle) {
+	if (PyDataType_FLAGCHK(typecode, NPY_LIST_PICKLE)) {
 		if (!PyList_Check(rawdata)) {
 			PyErr_SetString(PyExc_TypeError,
 					"object pickle not returning list");
@@ -1187,7 +1188,7 @@
 					   &(self->flags));
 	}
 
-	if (typecode->hasobject != 1 && !typecode->f->listpickle) {
+	if (!PyDataType_FLAGCHK(typecode, NPY_LIST_PICKLE)) {
                 int swap=!PyArray_ISNOTSWAPPED(self);
 		self->data = datastr;
 		if (!_IsAligned(self) || swap) {
@@ -1234,7 +1235,8 @@
 			if (self->dimensions) PyDimMem_FREE(self->dimensions);
 			return PyErr_NoMemory();
 		}
-		if (self->descr->hasobject) memset(self->data, 0, PyArray_NBYTES(self));
+		if (PyDataType_FLAGCHK(self->descr, NPY_NEEDS_INIT))
+                        memset(self->data, 0, PyArray_NBYTES(self));
 		self->flags |= OWNDATA;
 		self->base = NULL;
 		if (_setlist_pkl(self, rawdata) < 0)

Modified: trunk/numpy/core/src/arrayobject.c
===================================================================
--- trunk/numpy/core/src/arrayobject.c	2006-10-27 21:42:27 UTC (rev 3410)
+++ trunk/numpy/core/src/arrayobject.c	2006-10-28 09:18:00 UTC (rev 3411)
@@ -46,7 +46,7 @@
 static int
 _check_object_rec(PyArray_Descr *descr)
 {
-        if (descr->hasobject && !PyDescr_ISOBJECT(descr)) {
+        if (PyDataType_HASFIELDS(descr) && PyDataType_REFCHK(descr)) {
                 PyErr_SetString(PyExc_TypeError, "Not supported for this data-type.");
                 return -1;
         }
@@ -154,7 +154,7 @@
 {
         PyObject **temp;
 
-        if (descr->hasobject == 0) return;
+        if (!PyDataType_REFCHK(descr)) return;
 
         if (descr->type_num == PyArray_OBJECT) {
                 temp = (PyObject **)data;
@@ -182,7 +182,7 @@
 {
         PyObject **temp;
 
-        if (descr->hasobject == 0) return;
+        if (!PyDataType_REFCHK(descr)) return;
 
         if (descr->type_num == PyArray_OBJECT) {
                 temp = (PyObject **)data;
@@ -216,7 +216,7 @@
         PyObject **data, **temp;
         PyArrayIterObject *it;
 
-        if (mp->descr->hasobject == 0) return 0;
+        if (!PyDataType_REFCHK(mp->descr)) return 0;
 
         if (mp->descr->type_num != PyArray_OBJECT) {
                 it = (PyArrayIterObject *)PyArray_IterNew((PyObject *)mp);
@@ -267,7 +267,7 @@
         PyObject **temp;
         PyArrayIterObject *it;
 
-        if (mp->descr->hasobject == 0) return 0;
+        if (!PyDataType_REFCHK(mp->descr)) return 0;
 
         if (mp->descr->type_num != PyArray_OBJECT) {
                 it = (PyArrayIterObject *)PyArray_IterNew((PyObject *)mp);
@@ -1314,16 +1314,14 @@
         int swap;
 
         type_num = descr->type_num;
-        type = descr->typeobj;
         if (type_num == PyArray_BOOL)
                 PyArrayScalar_RETURN_BOOL_FROM_LONG(*(Bool*)data);
-        else if (type_num == PyArray_OBJECT ||           
-                 (PyTypeNum_ISUSERDEF(type_num) &&
-                  !(PyType_IsSubtype(type, &PyGenericArrType_Type)))) {
+        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;
@@ -1705,8 +1703,8 @@
 
         n3 = (sep ? strlen((const char *)sep) : 0);
         if (n3 == 0) { /* binary data */
-                if (self->descr->hasobject) {
-                        PyErr_SetString(PyExc_ValueError, "cannot write "\
+                if (PyDataType_FLAGCHK(self->descr, NPY_LIST_PICKLE)) {
+                        PyErr_SetString(PyExc_ValueError, "cannot write " \
                                         "object arrays to a file in "   \
                                         "binary mode");
                         return -1;
@@ -1934,7 +1932,7 @@
 
         if ((self->flags & OWNDATA) && self->data) {
                 /* Free internal references if an Object array */
-                if (self->descr->hasobject) {
+                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
@@ -2443,7 +2441,7 @@
         copyswap = PyArray_DESCR(arr)->f->copyswap;
         PyArray_MapIterReset(mit);
         /* Need to decref hasobject arrays */
-        if (descr->hasobject) {
+        if (PyDataType_FLAGCHK(descr, NPY_ITEM_REFCOUNT)) {
                 while (index--) {
                         PyArray_Item_XDECREF(mit->dataptr, PyArray_DESCR(arr));
                         PyArray_Item_INCREF(it->dataptr, PyArray_DESCR(arr));
@@ -5368,7 +5366,7 @@
 
                 /* It is bad to have unitialized OBJECT pointers */
                 /* which could also be sub-fields of a VOID array */
-                if (descr->hasobject) {
+                if (PyDataType_FLAGCHK(descr, NPY_NEEDS_INIT)) {
                         memset(data, 0, sd);
                 }
         }
@@ -5431,15 +5429,9 @@
 static void
 _putzero(char *optr, PyObject *zero, PyArray_Descr *dtype)
 {
-        if (dtype->hasobject == 0) {
+        if (!PyDataType_FLAGCHK(dtype, NPY_ITEM_REFCOUNT)) {
                 memset(optr, 0, dtype->elsize);
         }
-        else if (PyDescr_ISOBJECT(dtype)) {
-                PyObject **temp;
-                Py_INCREF(zero);
-                temp = (PyObject **)optr;
-                *temp = zero;
-        }
         else if (PyDescr_HASFIELDS(dtype)) {
                 PyObject *key, *value, *title=NULL;
                 PyArray_Descr *new;
@@ -5451,6 +5443,12 @@
                         _putzero(optr + offset, zero, new);
                 }
         }
+        else {
+                PyObject **temp;
+                Py_INCREF(zero);
+                temp = (PyObject **)optr;
+                *temp = zero;
+        }
         return;
 }
 
@@ -5483,12 +5481,6 @@
                 return NULL;
         }
 
-        if (self->descr->hasobject) {
-                PyErr_SetString(PyExc_ValueError,
-                                "cannot resize an object-array like this");
-                return NULL;
-        }
-
         if (fortran == PyArray_ANYORDER)
                 fortran = PyArray_CORDER;
 
@@ -5547,7 +5539,7 @@
         if ((newsize > oldsize) && PyArray_ISWRITEABLE(self)) {
                 /* Fill new memory with zeros */
                 elsize = self->descr->elsize;
-                if (self->descr->hasobject) {
+                if (PyDataType_FLAGCHK(self->descr, NPY_ITEM_REFCOUNT)) {
                         PyObject *zero = PyInt_FromLong(0);
                         char *optr;
                         optr = self->data + oldsize*elsize;
@@ -5595,7 +5587,7 @@
 static void
 _fillobject(char *optr, PyObject *obj, PyArray_Descr *dtype)
 {
-        if (!dtype->hasobject) {
+        if (!PyDataType_FLAGCHK(dtype, NPY_ITEM_REFCOUNT)) {
                 if ((obj == Py_None) ||
                     (PyInt_Check(obj) && PyInt_AsLong(obj)==0))
                         return;
@@ -5610,14 +5602,7 @@
                         Py_XDECREF(arr);
                 }
         }
-        if (PyDescr_ISOBJECT(dtype)) {
-                PyObject **temp;
-                Py_XINCREF(obj);
-                temp = (PyObject **)optr;
-                *temp = obj;
-                return;
-        }
-        if (PyDescr_HASFIELDS(dtype)) {
+        else if (PyDescr_HASFIELDS(dtype)) {
                 PyObject *key, *value, *title=NULL;
                 PyArray_Descr *new;
                 int offset;
@@ -5628,6 +5613,13 @@
                         _fillobject(optr + offset, obj, new);
                 }
         }
+        else {
+                PyObject **temp;
+                Py_XINCREF(obj);
+                temp = (PyObject **)optr;
+                *temp = obj;
+                return;
+        }
 }
 
 /* Assumes contiguous */
@@ -5815,7 +5807,8 @@
                                              dims.ptr,
                                              strides.ptr, NULL, fortran, NULL);
                 if (ret == NULL) {descr=NULL;goto fail;}
-                if (descr->hasobject) { /* place Py_None in object positions */
+                if (PyDataType_FLAGCHK(descr, NPY_ITEM_HASOBJECT)) { 
+                        /* place Py_None in object positions */
                         PyArray_FillObjectArray(ret, Py_None);
                         if (PyErr_Occurred()) {
                                 descr=NULL;
@@ -6235,9 +6228,12 @@
                 PyErr_SetString(PyExc_TypeError, "invalid data-type for array");
                 return -1;
         }
-        if (newtype->hasobject || self->descr->hasobject) {
-                PyErr_SetString(PyExc_TypeError,                        \
-                                "Cannot change data-type for object"    \
+        if (PyDataType_FLAGCHK(newtype, NPY_ITEM_HASOBJECT) ||
+            PyDataType_FLAGCHK(newtype, NPY_ITEM_IS_POINTER) ||
+            PyDataType_FLAGCHK(self->descr, NPY_ITEM_HASOBJECT) || 
+            PyDataType_FLAGCHK(self->descr, NPY_ITEM_IS_POINTER)) {
+                PyErr_SetString(PyExc_TypeError,                      \
+                                "Cannot change data-type for object " \
                                 "array.");
                 Py_DECREF(newtype);
                 return -1;
@@ -6535,7 +6531,7 @@
 
         swap = PyArray_ISNOTSWAPPED(self) != PyArray_ISNOTSWAPPED(arr);
         copyswap = self->descr->f->copyswap;
-        if (self->descr->hasobject) {
+        if (PyDataType_REFCHK(self->descr)) {
                 while(selfit->index < selfit->size) {
                         PyArray_Item_XDECREF(selfit->dataptr, self->descr);
                         PyArray_Item_INCREF(arrit->dataptr, PyArray_DESCR(arr));
@@ -7520,9 +7516,9 @@
                 PyErr_NoMemory();
                 return -1;
         }
-        if (out->descr->hasobject)
+        if (PyDataType_FLAGCHK(out->descr, NPY_NEEDS_INIT))
                 memset(buffers[0], 0, N*delsize);
-        if (in->descr->hasobject)
+        if (PyDataType_FLAGCHK(in->descr, NPY_NEEDS_INIT))
                 memset(buffers[1], 0, N*selsize);
 
 #if NPY_ALLOW_THREADS
@@ -7548,12 +7544,12 @@
                         }
 #endif
         Py_DECREF(multi);
-        if (in->descr->hasobject) {
+        if (PyDataType_REFCHK(in->descr)) {
                 obptr = buffers[1];
                 for (i=0; i<N; i++, obptr+=selsize)
                         PyArray_Item_XDECREF(obptr, out->descr);
         }
-        if (out->descr->hasobject) {
+        if (PyDataType_REFCHK(out->descr)) {
                 obptr = buffers[0];
                 for (i=0; i<N; i++, obptr+=delsize)
                         PyArray_Item_XDECREF(obptr, out->descr);
@@ -10617,7 +10613,10 @@
         {"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},
+        /* Get rid of this in 1.1 */
         {"hasobject", T_UBYTE, offsetof(PyArray_Descr, hasobject), RO, NULL},
+        /* END */
+        {"flags", T_UBYTE, offsetof(PyArray_Descr, hasobject), RO, NULL},
         {"names", T_OBJECT, offsetof(PyArray_Descr, names), RO, NULL},
         {NULL},
 };
@@ -10870,7 +10869,7 @@
         /* 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 = 2;
+        const int version = 3;
         PyObject *ret, *mod, *obj;
         PyObject *state;
         char endian;
@@ -10906,7 +10905,7 @@
                 endian = '<';
                 if (!PyArray_IsNativeByteOrder(endian)) endian = '>';
         }
-        state = PyTuple_New(7);
+        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));
@@ -10932,6 +10931,7 @@
 
         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;
@@ -10944,8 +10944,9 @@
 static int
 _descr_find_object(PyArray_Descr *self)
 {
-        if (self->hasobject || self->type_num == PyArray_OBJECT || self->kind == 'O')
-                return 1;
+        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;
@@ -10958,8 +10959,8 @@
                                 return 0;
                         }
                         if (_descr_find_object(new)) {
-                                new->hasobject = 1;
-                                return 1;
+                                new->hasobject = NPY_OBJECT_DTYPE_FLAGS;
+                                return NPY_OBJECT_DTYPE_FLAGS;
                         }
                 }
         }
@@ -10974,27 +10975,62 @@
 arraydescr_setstate(PyArray_Descr *self, PyObject *args)
 {
         int elsize = -1, alignment = -1;
-        int version = 2;
+        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 (!PyArg_ParseTuple(args, "(icOOOii)", &version, &endian, &subarray,
-                              &names, &fields, &elsize, &alignment)) {
-            PyErr_Clear();
-            if (!PyArg_ParseTuple(args, "(icOOii)", &version, &endian,
-                                  &subarray, &fields, &elsize,
-                                  &alignment)) {
-                PyErr_Clear();
+        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;
+                if (!PyArg_ParseTuple(args, "(cOOii)", 
+                                      &endian, &subarray, &fields, &elsize, 
+                                      &alignment)) {
+                        return NULL;
                 }
-            }
+                break;
+        default:
+                version = -1; /* raise an error */
         }
+        
+        /* 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) {
@@ -11010,18 +11046,8 @@
             else {
                 names = Py_None;
             }
-            version = 2;
         }
 
-        /* If we ever need another pickle format, increment the version
-           number. But we should still be able to handle the old versions.
-        */
-        if (version != 2) {
-            PyErr_Format(PyExc_ValueError,
-                         "can't handle version %d of numpy.dtype pickle",
-                         version);
-            return NULL;
-        }
 
         if ((fields == Py_None && names != Py_None) ||  \
             (names == Py_None && fields != Py_None)) {
@@ -11064,7 +11090,10 @@
                 self->alignment = alignment;
         }
 
-        self->hasobject = _descr_find_object(self);
+        self->hasobject = dtypeflags;
+        if (version < 3) {
+                self->hasobject = _descr_find_object(self);
+        }
         Py_INCREF(Py_None);
         return Py_None;
 }

Modified: trunk/numpy/core/src/arraytypes.inc.src
===================================================================
--- trunk/numpy/core/src/arraytypes.inc.src	2006-10-27 21:42:27 UTC (rev 3410)
+++ trunk/numpy/core/src/arraytypes.inc.src	2006-10-28 09:18:00 UTC (rev 3411)
@@ -514,7 +514,8 @@
         }
 
  finish:
-        if (descr->hasobject) {
+        if (PyDataType_FLAGCHK(descr, NPY_ITEM_HASOBJECT) ||
+            PyDataType_FLAGCHK(descr, NPY_ITEM_IS_POINTER)) {                
                 PyErr_SetString(PyExc_ValueError,
                                 "tried to get void-array with object"
                                 " members as buffer.");
@@ -622,7 +623,8 @@
         {
                 const void *buffer;
                 Py_ssize_t buflen;
-                if (descr->hasobject) {
+                if (PyDataType_FLAGCHK(descr, NPY_ITEM_HASOBJECT) ||
+                    PyDataType_FLAGCHK(descr, NPY_ITEM_IS_POINTER)) {
                         PyErr_SetString(PyExc_ValueError,
                                         "tried to set void-array with object"
                                         " members using buffer.");
@@ -2105,7 +2107,7 @@
 #NAME= Bool, Byte, UByte, Short, UShort, Int, UInt, Long, ULong, LongLong, ULongLong, Float, Double, LongDouble, CFloat, CDouble, CLongDouble, Object#
 #kind= GENBOOL, SIGNED, UNSIGNED, SIGNED, UNSIGNED, SIGNED, UNSIGNED, SIGNED, UNSIGNED, SIGNED, UNSIGNED, FLOATING, FLOATING, FLOATING, COMPLEX, COMPLEX, COMPLEX, OBJECT#
 #endian= |*3, =*14, |#
-#isobject= 0*17,1#
+#isobject= 0*17,NPY_OBJECT_DTYPE_FLAGS#
 */
 
 static PyArray_ArrFuncs _Py at NAME@_ArrFuncs = {
@@ -2154,7 +2156,7 @@
         (PyArray_ScalarKindFunc*)NULL,
         NULL,
         NULL,
-        0
+        0,
 };
 
 static PyArray_Descr @from at _Descr = {

Modified: trunk/numpy/core/src/multiarraymodule.c
===================================================================
--- trunk/numpy/core/src/multiarraymodule.c	2006-10-27 21:42:27 UTC (rev 3410)
+++ trunk/numpy/core/src/multiarraymodule.c	2006-10-28 09:18:00 UTC (rev 3411)
@@ -2571,7 +2571,9 @@
 				     "merge sort not available for item %d", i);
 			goto fail;
 		}
-		if (!object && mps[i]->descr->hasobject) object = 1;
+		if (!object && 
+                    PyDataType_FLAGCHK(mps[i]->descr, NPY_NEEDS_PYAPI))
+                        object = 1;
 		its[i] = (PyArrayIterObject *)PyArray_IterAllButAxis	\
 			((PyObject *)mps[i], &axis);
 		if (its[i]==NULL) goto fail;
@@ -3715,7 +3717,7 @@
         if (values == NULL) goto fail;
         nv = PyArray_SIZE(values);
         if (nv <= 0) goto finish;
-        if (self->descr->hasobject) {
+        if (PyDataType_REFCHK(self->descr)) {
                 switch(clipmode) {
                 case NPY_RAISE:
                         for(i=0; i<ni; i++) {
@@ -3891,7 +3893,7 @@
                 return Py_None;
         }
         if (nv > 0) {
-                if (self->descr->hasobject) {
+                if (PyDataType_REFCHK(self->descr)) {
                         for(i=0; i<ni; i++) {
                                 src = values->data + chunk * (i % nv);
                                 tmp = ((Bool *)(mask->data))[i];
@@ -4337,9 +4339,8 @@
                 new->names = conv->names;
                 Py_XINCREF(new->names);
 	}
+        new->hasobject = conv->hasobject;
 	Py_DECREF(conv);
-        if (conv->hasobject)
-                new->hasobject = 1;
 	*errflag = 0;
 	return new;
 
@@ -4417,7 +4418,7 @@
 		PyDimMem_FREE(shape.ptr);
 		newdescr->subarray = _pya_malloc(sizeof(PyArray_ArrayDescr));
 		newdescr->subarray->base = type;
-		if (type->hasobject) newdescr->hasobject = 1;
+                newdescr->hasobject = type->hasobject;
 		Py_INCREF(val);
 		newdescr->subarray->shape = val;
 		Py_XDECREF(newdescr->fields);
@@ -4448,8 +4449,9 @@
 	PyObject *nameslist;
 	PyArray_Descr *new;
 	PyArray_Descr *conv;
-        int hasobject=0;
+        int dtypeflags=0;
 
+
 	n = PyList_GET_SIZE(obj);
 	nameslist = PyTuple_New(n);
 	if (!nameslist) return NULL;
@@ -4505,8 +4507,7 @@
 					"two fields with the same name");
                         goto fail;
                 }
-                if (!hasobject && conv->hasobject)
-                        hasobject = 1;
+                dtypeflags |= (conv->hasobject & NPY_FROM_FIELDS);
 		tup = PyTuple_New((title == NULL ? 2 : 3));
 		PyTuple_SET_ITEM(tup, 0, (PyObject *)conv);
 		PyTuple_SET_ITEM(tup, 1, PyInt_FromLong((long) totalsize));
@@ -4528,7 +4529,7 @@
 	new->fields = fields;
         new->names = nameslist;
 	new->elsize = totalsize;
-        new->hasobject=hasobject;
+        new->hasobject=dtypeflags;
 	return new;
 
  fail:
@@ -4558,7 +4559,7 @@
 	PyObject *nameslist=NULL;
        	int ret;
 	int maxalign=0;
-        int hasobject=0;
+        int dtypeflags=0;
 
 	n = PyList_GET_SIZE(obj);
 	/* Ignore any empty string at end which _internal._commastring
@@ -4580,8 +4581,7 @@
 			Py_DECREF(key);
 			goto fail;
 		}
-		if (!hasobject && conv->hasobject)
-			hasobject=1;
+                dtypeflags |= (conv->hasobject & NPY_FROM_FIELDS);
 		PyTuple_SET_ITEM(tup, 0, (PyObject *)conv);
 		if (align) {
 			int _align;
@@ -4599,7 +4599,7 @@
 	new = PyArray_DescrNewFromType(PyArray_VOID);
 	new->fields = fields;
         new->names = nameslist;
-        new->hasobject=hasobject;
+        new->hasobject=dtypeflags;
 	if (maxalign > 1) {
 		totalsize = ((totalsize+maxalign-1)/maxalign)*maxalign;
 	}
@@ -4709,7 +4709,7 @@
 	int n, i;
 	int totalsize;
 	int maxalign=0;
-        int hasobject=0;
+        int dtypeflags=0;
 
 	fields = PyDict_New();
 	if (fields == NULL) return (PyArray_Descr *)PyErr_NoMemory();
@@ -4815,8 +4815,7 @@
 		}
 		Py_DECREF(tup);
 		if ((ret == PY_FAIL) || (newdescr->elsize == 0)) goto fail;
-                if (!hasobject && newdescr->hasobject)
-                        hasobject = 1;
+                dtypeflags |= (newdescr->hasobject & NPY_FROM_FIELDS);
 		totalsize += newdescr->elsize;
 	}
 
@@ -4834,7 +4833,7 @@
         }
         new->names = names;
 	new->fields = fields;
-        new->hasobject=hasobject;
+        new->hasobject = dtypeflags;
 	return new;
 
  fail:
@@ -5415,7 +5414,7 @@
 						    fortran, NULL);
 	if (ret == NULL) return NULL;
 
-	if (type->hasobject) {
+	if (PyDataType_REFCHK(type)) {
                 PyArray_FillObjectArray(ret, Py_None);
 		if (PyErr_Occurred()) {Py_DECREF(ret); return NULL;}
 	}
@@ -5476,8 +5475,8 @@
 				"itemsize cannot be zero");
 		return NULL;
 	}
-
-	if (typecode->type_num == PyArray_OBJECT || typecode->f->listpickle) {
+        
+	if (PyDataType_FLAGCHK(typecode, NPY_ITEM_IS_POINTER)) {
 		if (obj == NULL) obj = Py_None;
 		dptr = &obj;
 	}
@@ -5534,7 +5533,7 @@
 						    fortran, NULL);
 	if (ret == NULL) return NULL;
 
-	if (type->hasobject) {
+	if (PyDataType_REFCHK(type)) {
 		PyObject *zero = PyInt_FromLong(0);
                 PyArray_FillObjectArray(ret, zero);
                 Py_DECREF(zero);
@@ -5617,8 +5616,8 @@
 
 	if (dtype == NULL)
 		dtype=PyArray_DescrFromType(PyArray_DEFAULT);
-
-        if (dtype->hasobject) {
+        
+        if (PyDataType_FLAGCHK(dtype, NPY_ITEM_IS_POINTER)) {
                 PyErr_SetString(PyExc_ValueError,
                                 "Cannot create an object array from"    \
                                 " a string");
@@ -5797,9 +5796,9 @@
         elsize = dtype->elsize;
 
         /* We would need to alter the memory RENEW code to decrement any
-           reference counts before just throwing away the memory.
+           reference counts before throwing away any memory.
          */
-        if (dtype->hasobject) {
+        if (PyDataType_REFCHK(dtype)) {
                 PyErr_SetString(PyExc_ValueError, "cannot create "\
                                 "object arrays from iterator");
                 goto done;
@@ -5911,7 +5910,7 @@
 	PyArray_ScanFunc *scan;
 	Bool binary;
 
-        if (typecode->hasobject) {
+        if (PyDataType_REFCHK(typecode)) {
                 PyErr_SetString(PyExc_ValueError, "cannot read into"
                                 "object array");
                 Py_DECREF(typecode);
@@ -6105,7 +6104,7 @@
 	int write=1;
 
 
-	if (type->hasobject) {
+	if (PyDataType_REFCHK(type)) {
 		PyErr_SetString(PyExc_ValueError,
 				"cannot create an OBJECT array from memory"\
 				" buffer");
@@ -7227,29 +7226,28 @@
 	s = PyString_FromString("3.0");
 	PyDict_SetItemString(d, "__version__", s);
 	Py_DECREF(s);
-	s = PyInt_FromLong(NPY_ALLOW_THREADS);
-	PyDict_SetItemString(d, "ALLOW_THREADS", s);
-	Py_DECREF(s);
 
-	s = PyInt_FromLong(NPY_BUFSIZE);
-	PyDict_SetItemString(d, "BUFSIZE", s);
-	Py_DECREF(s);
+#define ADDCONST(NAME) \
+        s = PyInt_FromLong(NPY_##NAME); \
+        PyDict_SetItemString(d, #NAME, s); \
+        Py_DECREF(s)
 
-	s = PyInt_FromLong(NPY_CLIP);
-	PyDict_SetItemString(d, "CLIP", s);
-	Py_DECREF(s);
 
-	s = PyInt_FromLong(NPY_RAISE);
-	PyDict_SetItemString(d, "RAISE", s);
-	Py_DECREF(s);
+        ADDCONST(ALLOW_THREADS);
+        ADDCONST(BUFSIZE);
+        ADDCONST(CLIP);
 
-	s = PyInt_FromLong(NPY_WRAP);
-	PyDict_SetItemString(d, "WRAP", s);
-	Py_DECREF(s);
+        ADDCONST(ITEM_HASOBJECT);
+        ADDCONST(LIST_PICKLE);
+        ADDCONST(ITEM_IS_POINTER);
+        ADDCONST(NEEDS_INIT);
+        ADDCONST(NEEDS_PYAPI);
+        ADDCONST(USE_GETITEM);
 
-	s = PyInt_FromLong(NPY_MAXDIMS);
-	PyDict_SetItemString(d, "MAXDIMS", s);
-	Py_DECREF(s);
+        ADDCONST(RAISE);
+        ADDCONST(WRAP);
+        ADDCONST(MAXDIMS);
+#undef ADDCONST
 
 	Py_INCREF(&PyArray_Type);
 	PyDict_SetItemString(d, "ndarray", (PyObject *)&PyArray_Type);



More information about the Numpy-svn mailing list