summaryrefslogtreecommitdiff
path: root/scipy/base/src
diff options
context:
space:
mode:
Diffstat (limited to 'scipy/base/src')
-rw-r--r--scipy/base/src/arraymethods.c50
-rw-r--r--scipy/base/src/arrayobject.c160
-rw-r--r--scipy/base/src/arraytypes.inc.src26
-rw-r--r--scipy/base/src/multiarraymodule.c68
-rw-r--r--scipy/base/src/scalartypes.inc.src10
5 files changed, 248 insertions, 66 deletions
diff --git a/scipy/base/src/arraymethods.c b/scipy/base/src/arraymethods.c
index 9530b1520..0cca98896 100644
--- a/scipy/base/src/arraymethods.c
+++ b/scipy/base/src/arraymethods.c
@@ -854,6 +854,8 @@ array_reduce(PyArrayObject *self, PyObject *args)
{
PyObject *ret=NULL, *state=NULL, *obj=NULL, *mod=NULL;
PyObject *mybool, *thestr=NULL;
+ PyArray_Descr *descr;
+ char endian;
/* Return a tuple of (callable object, arguments, object's state) */
/* We will put everything in the object's state, so that on UnPickle
@@ -862,10 +864,10 @@ array_reduce(PyArrayObject *self, PyObject *args)
ret = PyTuple_New(3);
if (ret == NULL) return NULL;
mod = PyImport_ImportModule("scipy.base.multiarray");
- if (mod == NULL) return NULL;
+ if (mod == NULL) {Py_DECREF(ret); return NULL;}
obj = PyObject_GetAttrString(mod, "empty");
Py_DECREF(mod);
- if (obj == NULL) return NULL;
+ if (obj == NULL) {Py_DECREF(ret); return NULL;}
PyTuple_SET_ITEM(ret, 0, obj);
PyTuple_SET_ITEM(ret, 1,
Py_BuildValue("NNN",
@@ -873,14 +875,13 @@ array_reduce(PyArrayObject *self, PyObject *args)
PyInt_FromLong(0)),
PyObject_GetAttrString((PyObject *)self,
"dtypechar"),
- PyInt_FromLong((long) 0)));
+ PyInt_FromLong((long) self->descr->elsize)));
/* Now fill in object's state. This is a tuple with
4 arguments
1) a Tuple giving the shape
- 2) a string giving the typestr (> or < indicates byte order
- if swap is possibly needed)
+ 2) a PyArray_Descr Object (with correct bytorder set)
3) a Bool stating if Fortran or not
4) a binary string with the data (or a list for Object arrays)
@@ -893,9 +894,24 @@ array_reduce(PyArrayObject *self, PyObject *args)
Py_DECREF(ret); return NULL;
}
PyTuple_SET_ITEM(state, 0, PyObject_GetAttrString((PyObject *)self,
- "shape"));
- PyTuple_SET_ITEM(state, 1, PyObject_GetAttrString((PyObject *)self,
- "dtypestr"));
+ "shape"));
+ endian = self->descr->byteorder;
+ if ((endian == '=') || (PyArray_ISNOTSWAPPED(self) != \
+ PyArray_IsNativeByteOrder(endian))) {
+ descr = PyArray_DescrNew(self->descr);
+ endian = '<';
+ if (!PyArray_IsNativeByteOrder(endian)) endian = '>';
+ if (!PyArray_ISNOTSWAPPED(self)) {
+ if (endian == '<') endian = '>';
+ else endian = '<';
+ }
+ descr->byteorder = endian;
+ }
+ else {
+ descr = self->descr;
+ Py_INCREF(descr);
+ }
+ PyTuple_SET_ITEM(state, 1, (PyObject *)descr);
mybool = (PyArray_ISFORTRAN(self) ? Py_True : Py_False);
Py_INCREF(mybool);
PyTuple_SET_ITEM(state, 2, mybool);
@@ -919,8 +935,7 @@ static char doc_setstate[] = "a.__setstate__(tuple) for unpickling.";
/*
1) a Tuple giving the shape
- 2) a string giving the typestr (> or < indicates byte order
- if swap is possibly needed)
+ 2) a PyArray_Descr Object
3) a Bool stating if Fortran or not
4) a binary string with the data (or a list if Object array)
*/
@@ -939,25 +954,21 @@ array_setstate(PyArrayObject *self, PyObject *args)
long fortran;
PyObject *rawdata;
char *datastr;
- const char *typestr;
- int len, typestrlen;
- int swap;
+ int len;
intp dimensions[MAX_DIMS];
int nd;
/* This will free any memory associated with a and
use the string in setstate as the (writeable) memory.
*/
- if (!PyArg_ParseTuple(args, "(O!z#iO)", &PyTuple_Type,
- &shape, &typestr, &typestrlen,
+ if (!PyArg_ParseTuple(args, "(O!O!iO)", &PyTuple_Type,
+ &shape, &PyArrayDescr_Type, &typecode,
&fortran, &rawdata))
return NULL;
- typecode = _array_typedescr_fromstr((char *)typestr, &swap);
- if (typecode == NULL) return NULL;
-
Py_XDECREF(self->descr);
self->descr = typecode;
+ Py_INCREF(typecode);
nd = PyArray_IntpFromSequence(shape, dimensions, MAX_DIMS);
if (typecode->type_num == PyArray_OBJECT) {
if (!PyList_Check(rawdata)) {
@@ -1030,7 +1041,8 @@ array_setstate(PyArrayObject *self, PyObject *args)
self->base = rawdata;
Py_INCREF(self->base);
}
- if (swap) self->flags &= ~NOTSWAPPED;
+ if (!PyArray_IsNativeByteOrder(typecode->byteorder))
+ self->flags &= ~NOTSWAPPED;
}
else {
self->data = PyDataMem_NEW(PyArray_NBYTES(self));
diff --git a/scipy/base/src/arrayobject.c b/scipy/base/src/arrayobject.c
index 603747779..ba4d17762 100644
--- a/scipy/base/src/arrayobject.c
+++ b/scipy/base/src/arrayobject.c
@@ -3538,9 +3538,11 @@ PyArray_NewFromDescr(PyTypeObject *subtype, PyArray_Descr *descr, int nd,
this to be reset if truly
desired */
}
- if (descr->byteorder != '=' && \
- !PyArray_IsNativeByteOrder(descr->byteorder)) {
- self->flags &= ~NOTSWAPPED;
+ if ((descr->byteorder != '=') && (descr->byteorder != '|')) {
+ if (PyArray_IsNativeByteOrder(descr->byteorder))
+ self->flags |= NOTSWAPPED;
+ else
+ self->flags &= ~NOTSWAPPED;
}
self->data = data;
@@ -4706,10 +4708,22 @@ array_alloc(PyTypeObject *type, int nitems)
static char Arraytype__doc__[] =
"A array object represents a multidimensional, homogeneous array\n"
- " of basic values. Arrays are sequence, mapping and numeric\n"
- " objects. More information is available in the scipy module and\n"
- " by looking at the methods and attributes of an array.";
-
+ " of fixed-size items. An associated data-type-descriptor object details\n"
+ " the data-type in an array (including any fields). An array can be\n"
+ " constructed using the scipy.array command. Arrays are sequence, mapping\n"
+ " and numeric objects. More information is available in the scipy module\n"
+ " and by looking at the methods and attributes of an array.\n\n"
+ " ndarray.__new__(subtype, shape=, dtype=long_, buffer=None, offset=0,\n"
+ " strides=None, swap=0, fortran=False)\n\n"
+ " There are two modes of creating an array using the __new__ method:\n"
+ " 1) If buffer is None, then only shape, dtype, and fortran are used\n"
+ " 2) If buffer is an object exporting the buffer interface, then all\n"
+ " keywords are interpreted.\n"
+ " The dtype parameter can be any object that can be interpreted as a\n"
+ " scipy.dtypedescr object.\n\n"
+ " No __init__ method is needed because the array is fully initialized\n"
+ " after the __new__ method.";
+
static PyTypeObject PyBigArray_Type = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
@@ -8019,28 +8033,150 @@ static PyObject *
arraydescr_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
{
PyObject *odescr;
- PyArray_Descr *descr;
+ PyArray_Descr *descr, *conv;
int align=0;
if (!PyArg_ParseTuple(args, "O|i", &odescr, &align))
return NULL;
-
+
if (align) {
if PyDict_Check(odescr)
return (PyObject *)_convert_from_dict(odescr, 1);
if PyList_Check(odescr)
return (PyObject *)_convert_from_list(odescr, 1);
}
- if (!PyArray_DescrConverter(odescr, &descr))
+ if (!PyArray_DescrConverter(odescr, &conv))
return NULL;
+ /* Get a new copy of it */
+ descr = PyArray_DescrNew(conv);
+ Py_DECREF(conv);
return (PyObject *)descr;
}
+static char doc_arraydescr_reduce[] = "self.__reduce__() for pickling.";
+
+/* return a tuple of (callable object, args, state) */
+static PyObject *
+arraydescr_reduce(PyArray_Descr *self, PyObject *args)
+{
+ PyObject *ret, *mod, *obj;
+ PyObject *state;
+ char endian;
+ int elsize, alignment;
+
+ ret = PyTuple_New(3);
+ if (ret == NULL) return NULL;
+ mod = PyImport_ImportModule("scipy.base.multiarray");
+ if (mod == NULL) {Py_DECREF(ret); return NULL;}
+ obj = PyObject_GetAttrString(mod, "dtypedescr");
+ Py_DECREF(mod);
+ if (obj == NULL) {Py_DECREF(ret); return NULL;}
+ PyTuple_SET_ITEM(ret, 0, obj);
+ if (PyTypeNum_ISUSERDEF(self->type_num)) {
+ obj = (PyObject *)self->typeobj;
+ Py_INCREF(obj);
+ }
+ else {
+ obj = PyString_FromFormat("%c%d",self->kind, self->elsize);
+ }
+ PyTuple_SET_ITEM(ret, 1, Py_BuildValue("(N)", obj));
+
+ /* 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(5);
+ PyTuple_SET_ITEM(state, 0, PyString_FromFormat("%c", endian));
+ PyTuple_SET_ITEM(state, 1, arraydescr_subdescr_get(self));
+ if (self->fields) {
+ Py_INCREF(self->fields);
+ PyTuple_SET_ITEM(state, 2, self->fields);
+ }
+ else {
+ PyTuple_SET_ITEM(state, 2, 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, 3, PyInt_FromLong(elsize));
+ PyTuple_SET_ITEM(state, 4, PyInt_FromLong(alignment));
+
+ PyTuple_SET_ITEM(ret, 2, state);
+ return ret;
+}
+
+
+
+/* state is at least byteorder, subarray, and fields but could include elsize
+ and alignment for EXTENDED arrays
+*/
+static char doc_arraydescr_setstate[] = "self.__setstate__() for pickling.";
+
+static PyObject *
+arraydescr_setstate(PyArray_Descr *self, PyObject *args)
+{
+ int elsize = -1, alignment = -1;
+ char endian;
+ PyObject *subarray, *fields;
+
+ if (!PyArg_ParseTuple(args, "(cOOii)", &endian, &subarray, &fields,
+ &elsize, &alignment)) return NULL;
+
+ if (PyArray_IsNativeByteOrder(endian)) endian = '=';
+
+ self->byteorder = endian;
+ if (self->subarray) {
+ Py_XDECREF(self->subarray->base);
+ Py_XDECREF(self->subarray->shape);
+ free(self->subarray);
+ }
+ self->subarray = NULL;
+
+ if (subarray != Py_None) {
+ self->subarray = 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);
+ }
+
+ if (PyTypeNum_ISEXTENDED(self->type_num)) {
+ self->elsize = elsize;
+ self->alignment = alignment;
+ }
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+static PyMethodDef arraydescr_methods[] = {
+ /* for pickling */
+ {"__reduce__", (PyCFunction)arraydescr_reduce, METH_VARARGS,
+ doc_arraydescr_reduce},
+ {"__setstate__", (PyCFunction)arraydescr_setstate, METH_VARARGS,
+ doc_arraydescr_setstate},
+ {NULL, NULL} /* sentinel */
+};
static PyTypeObject PyArrayDescr_Type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
- "scipy.datadescr", /* tp_name */
+ "scipy.dtypedescr", /* tp_name */
sizeof(PyArray_Descr), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
@@ -8067,7 +8203,7 @@ static PyTypeObject PyArrayDescr_Type = {
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
- 0, /* tp_methods */
+ arraydescr_methods, /* tp_methods */
arraydescr_members, /* tp_members */
arraydescr_getsets, /* tp_getset */
0, /* tp_base */
diff --git a/scipy/base/src/arraytypes.inc.src b/scipy/base/src/arraytypes.inc.src
index 87a93abe9..39ba44e66 100644
--- a/scipy/base/src/arraytypes.inc.src
+++ b/scipy/base/src/arraytypes.inc.src
@@ -1452,7 +1452,31 @@ OBJECT_dot(char *ip1, intp is1, char *ip2, intp is2, char *op, intp n,
}
#define BOOL_fill NULL
-#define OBJECT_fill NULL
+
+/* this requires buffer to be filled with objects or NULL */
+static void
+OBJECT_fill(PyObject **buffer, intp length, void *ignored)
+{
+ intp i;
+ PyObject *start = buffer[0];
+ PyObject *delta = buffer[1];
+ delta = PyNumber_Subtract(delta, start);
+ if (!delta) return;
+ start = PyNumber_Add(start, delta);
+ if (!start) goto finish;
+ buffer += 2;
+
+ for (i=2; i<length; i++, buffer++) {
+ start = PyNumber_Add(start, delta);
+ if (!start) goto finish;
+ Py_XDECREF(*buffer);
+ *buffer = start;
+ }
+
+ finish:
+ Py_DECREF(delta);
+ return;
+}
/**begin repeat
#NAME=BYTE,UBYTE,SHORT,USHORT,INT,UINT,LONG,ULONG,LONGLONG,ULONGLONG,FLOAT,DOUBLE,LONGDOUBLE#
diff --git a/scipy/base/src/multiarraymodule.c b/scipy/base/src/multiarraymodule.c
index 7c98f44e2..290226d56 100644
--- a/scipy/base/src/multiarraymodule.c
+++ b/scipy/base/src/multiarraymodule.c
@@ -2677,7 +2677,13 @@ PyArray_TypestrConvert(int itemsize, int gentype)
{
register int newtype = gentype;
- if (gentype == PyArray_SIGNEDLTR) {
+ if (gentype == PyArray_GENBOOLLTR) {
+ if (itemsize == 1)
+ newtype = PyArray_BOOL;
+ else
+ newtype = PyArray_NOTYPE;
+ }
+ else if (gentype == PyArray_SIGNEDLTR) {
switch(itemsize) {
case 1:
newtype = PyArray_INT8;
@@ -3310,24 +3316,23 @@ PyArray_DescrConverter(PyObject *obj, PyArray_Descr **at)
more than one byte and itemsize must be
the number of bytes.
*/
- if (check_num == PyArray_UNICODELTR)
+ if (elsize == 0) {
+ check_num = PyArray_NOTYPE+10;
+ }
+ else if (check_num == PyArray_UNICODELTR) {
elsize *= sizeof(Py_UNICODE);
-
+ }
/* Support for generic processing
c4, i4, f8, etc...
*/
else if ((check_num != PyArray_STRINGLTR) &&
(check_num != PyArray_VOIDLTR)) {
- if (elsize == 0) {
- /* reset because string conversion failed */
- check_num = PyArray_NOTYPE+10;
- }
- else {
- check_num = \
- PyArray_TypestrConvert(elsize,
- check_num);
- elsize = 0;
- }
+ check_num = \
+ PyArray_TypestrConvert(elsize,
+ check_num);
+ if (check_num == PyArray_NOTYPE)
+ check_num += 10;
+ elsize = 0;
}
}
}
@@ -3551,34 +3556,29 @@ array_empty(PyObject *ignored, PyObject *args, PyObject *kwds)
return ret;
}
-static char doc_scalar[] = "scalar(dtypestr,obj) will return a new scalar array of the given type initialized with obj. Mainly for pickle support. typestr must be a valid data typestr (complete with < > or |). If dtypestr is object, then obj can be any object, otherwise obj must be a string. If obj is not given it will be interpreted as None for object type and zeros for all other types.";
+static char doc_scalar[] = "scalar(dtypedescr,obj) will return a new scalar array of the given type initialized with obj. Mainly for pickle support. The dtypedescr must be a valid data-type descriptor. If dtypedescr corresponds to an OBJECT descriptor, then obj can be any object, otherwise obj must be a string. If obj is not given it will be interpreted as None for object type and zeros for all other types.";
static PyObject *
array_scalar(PyObject *ignored, PyObject *args, PyObject *kwds)
{
- static char *kwlist[] = {"dtypestr","obj", NULL};
+ static char *kwlist[] = {"dtypedescr","obj", NULL};
PyArray_Descr *typecode;
PyObject *obj=NULL;
- char *typestr;
- int typestrlen;
int swap, alloc=0;
void *dptr;
PyObject *ret;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "z#|O",
- kwlist, &typestr, &typestrlen,
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|O",
+ kwlist, &PyArrayDescr_Type,
+ &typecode,
&obj))
return NULL;
-
- if (!(typecode=_array_typedescr_fromstr(typestr, &swap)))
- return NULL;
-
+
if (typecode->elsize == 0) {
PyErr_SetString(PyExc_ValueError, \
"itemsize cannot be zero");
- Py_DECREF(typecode);
return NULL;
}
@@ -3591,7 +3591,6 @@ array_scalar(PyObject *ignored, PyObject *args, PyObject *kwds)
if (obj == NULL) {
dptr = malloc(typecode->elsize);
if (dptr == NULL) {
- Py_DECREF(typecode);
return PyErr_NoMemory();
}
memset(dptr, '\0', typecode->elsize);
@@ -3602,22 +3601,20 @@ array_scalar(PyObject *ignored, PyObject *args, PyObject *kwds)
PyErr_SetString(PyExc_TypeError,
"initializing object must "\
"be a string");
- Py_DECREF(typecode);
return NULL;
}
if (PyString_GET_SIZE(obj) < typecode->elsize) {
PyErr_SetString(PyExc_ValueError,
"initialization string is too"\
" small");
- Py_DECREF(typecode);
return NULL;
}
dptr = PyString_AS_STRING(obj);
}
+ swap = (!PyArray_IsNativeByteOrder(typecode->byteorder));
}
ret = PyArray_Scalar(dptr, swap, typecode, NULL);
- Py_DECREF(typecode);
/* free dptr which contains zeros */
if (alloc) free(dptr);
@@ -4190,6 +4187,7 @@ PyArray_Arange(double start, double stop, double step, int type_num)
PyObject *range;
PyArray_ArrFuncs *funcs;
PyObject *obj;
+ int ret;
length = (intp ) ceil((stop - start)/step);
@@ -4209,14 +4207,16 @@ PyArray_Arange(double start, double stop, double step, int type_num)
/* if length > 2, then call the inner loop, otherwise stop */
obj = PyFloat_FromDouble(start);
- funcs->setitem(obj, PyArray_DATA(range), (PyArrayObject *)range);
+ ret = funcs->setitem(obj, PyArray_DATA(range), (PyArrayObject *)range);
Py_DECREF(obj);
+ if (ret < 0) goto fail;
if (length == 1) return range;
obj = PyFloat_FromDouble(start + step);
- funcs->setitem(obj, PyArray_DATA(range)+PyArray_ITEMSIZE(range),
- (PyArrayObject *)range);
+ ret = funcs->setitem(obj, PyArray_DATA(range)+PyArray_ITEMSIZE(range),
+ (PyArrayObject *)range);
Py_DECREF(obj);
+ if (ret < 0) goto fail;
if (length == 2) return range;
if (!funcs->fill) {
@@ -4225,8 +4225,13 @@ PyArray_Arange(double start, double stop, double step, int type_num)
return NULL;
}
funcs->fill(PyArray_DATA(range), length, (PyArrayObject *)range);
+ if (PyErr_Occurred()) goto fail;
return range;
+
+ fail:
+ Py_DECREF(range);
+ return NULL;
}
/* the formula is
@@ -4343,6 +4348,7 @@ PyArray_ArangeObj(PyObject *start, PyObject *stop, PyObject *step, PyArray_Descr
goto fail;
}
funcs->fill(PyArray_DATA(range), length, (PyArrayObject *)range);
+ if (PyErr_Occurred()) goto fail;
finish:
Py_DECREF(start);
diff --git a/scipy/base/src/scalartypes.inc.src b/scipy/base/src/scalartypes.inc.src
index cac065ea6..5dfa914b6 100644
--- a/scipy/base/src/scalartypes.inc.src
+++ b/scipy/base/src/scalartypes.inc.src
@@ -1151,7 +1151,7 @@ gentype_reduce(PyObject *self, PyObject *args)
Py_DECREF(mod);
if (obj == NULL) return NULL;
PyTuple_SET_ITEM(ret, 0, obj);
- obj = PyObject_GetAttrString((PyObject *)self, "dtypestr");
+ obj = PyObject_GetAttrString((PyObject *)self, "dtypedescr");
if PyArray_IsScalar(self, Object) {
mod = ((PyObjectScalarObject *)self)->obval;
PyTuple_SET_ITEM(ret, 1,
@@ -1847,9 +1847,11 @@ PyArray_DescrFromTypeObject(PyObject *type)
PyArray_Descr *new, *conv=NULL;
/* if it's a builtin type, then use the typenumber */
- typenum = _typenum_fromtypeobj(type,0);
+ typenum = _typenum_fromtypeobj(type,1);
if (typenum != PyArray_NOTYPE) {
- return PyArray_DescrFromType(typenum);
+ new = PyArray_DescrFromType(typenum);
+ if (PyTypeNum_ISUSERDEF(typenum)) goto finish;
+ return new;
}
/* Check the generic types */
@@ -1879,6 +1881,8 @@ PyArray_DescrFromTypeObject(PyObject *type)
*/
/* look for a dtypedescr attribute */
new = PyArray_DescrNewFromType(PyArray_VOID);
+
+ finish:
conv = _arraydescr_fromobj(type);
if (conv) {
new->fields = conv->fields;