diff options
Diffstat (limited to 'scipy/base/src')
-rw-r--r-- | scipy/base/src/arraymethods.c | 22 | ||||
-rw-r--r-- | scipy/base/src/arrayobject.c | 118 | ||||
-rw-r--r-- | scipy/base/src/multiarraymodule.c | 33 | ||||
-rw-r--r-- | scipy/base/src/scalartypes.inc.src | 14 |
4 files changed, 171 insertions, 16 deletions
diff --git a/scipy/base/src/arraymethods.c b/scipy/base/src/arraymethods.c index b9548de57..1b597baf1 100644 --- a/scipy/base/src/arraymethods.c +++ b/scipy/base/src/arraymethods.c @@ -921,7 +921,7 @@ static intp _array_fill_strides(intp *, intp *, int, intp, int, int *); static int _IsAligned(PyArrayObject *); -static PyArray_Descr * _array_typedescr_fromstr(char *, int *); +static PyArray_Descr * _array_typedescr_fromstr(char *); static PyObject * array_setstate(PyArrayObject *self, PyObject *args) @@ -1503,6 +1503,24 @@ array_setflags(PyArrayObject *self, PyObject *args, PyObject *kwds) return Py_None; } +static char doc_newbyteorder[] = "a.newbyteorder(<byteorder>) is equivalent\n" \ + " to a.view(a.dtypedescr.newbytorder(<byteorder>))\n"; + +static PyObject * +array_newbyteorder(PyArrayObject *self, PyObject *args) +{ + char endian = PyArray_SWAP; + PyArray_Descr *new; + + if (!PyArg_ParseTuple(args, "|O&", PyArray_ByteorderConverter, + &endian)) return NULL; + + new = PyArray_DescrNewByteorder(self->descr, endian); + if (!new) return NULL; + return _ARET(PyArray_View(self, new)); + +} + static PyMethodDef array_methods[] = { {"tolist", (PyCFunction)array_tolist, 1, doc_tolist}, {"toscalar", (PyCFunction)array_toscalar, METH_VARARGS, doc_toscalar}, @@ -1612,6 +1630,8 @@ static PyMethodDef array_methods[] = { METH_VARARGS, doc_ravel}, {"setflags", (PyCFunction)array_setflags, METH_VARARGS|METH_KEYWORDS, doc_setflags}, + {"newbyteorder", (PyCFunction)array_newbyteorder, + METH_VARARGS, doc_newbyteorder}, {NULL, NULL} /* sentinel */ }; diff --git a/scipy/base/src/arrayobject.c b/scipy/base/src/arrayobject.c index fce6fd215..24351bb8d 100644 --- a/scipy/base/src/arrayobject.c +++ b/scipy/base/src/arrayobject.c @@ -4879,8 +4879,7 @@ _array_find_type(PyObject *op, PyArray_Descr *minitype, int max) if ((ip=PyObject_GetAttrString(op, "__array_typestr__"))!=NULL) { if (PyString_Check(ip)) { - chktype =_array_typedescr_fromstr \ - (PyString_AS_STRING(ip)); + chktype =_array_typedescr_fromstr(PyString_AS_STRING(ip)); } Py_DECREF(ip); if (chktype) goto finish; @@ -4890,13 +4889,12 @@ _array_find_type(PyObject *op, PyArray_Descr *minitype, int max) if ((ip=PyObject_GetAttrString(op, "__array_struct__")) != NULL) { PyArrayInterface *inter; char buf[40]; - int swap=0; if (PyCObject_Check(ip)) { inter=(PyArrayInterface *)PyCObject_AsVoidPtr(ip); if (inter->version == 2) { snprintf(buf, 40, "|%c%d", inter->typekind, inter->itemsize); - chktype = _array_typedescr_fromstr(buf, &swap); + chktype = _array_typedescr_fromstr(buf); } } Py_DECREF(ip); @@ -5597,11 +5595,10 @@ static PyObject * array_fromstructinterface(PyObject *input, PyArray_Descr *intype, int flags) { PyArray_Descr *thetype; - int swap; char buf[40]; PyArrayInterface *inter; PyObject *attr, *r, *ret; - char endian = PyArray_NATIVEBYTE; + char endian = PyArray_NATBYTE; attr = PyObject_GetAttrString(input, "__array_struct__"); if (attr == NULL) { @@ -5617,7 +5614,7 @@ array_fromstructinterface(PyObject *input, PyArray_Descr *intype, int flags) return NULL; } if ((inter->flags & NOTSWAPPED) != NOTSWAPPED) { - endian = PyArray_OPPOSITEBYTE; + endian = PyArray_OPPBYTE; inter->flags &= ~NOTSWAPPED; } @@ -5653,7 +5650,6 @@ array_frominterface(PyObject *input, PyArray_Descr *intype, int flags) int buffer_len; int res, i, n; intp dims[MAX_DIMS], strides[MAX_DIMS]; - int swap; int dataflags = BEHAVED_FLAGS; /* Get the memory from __array_data__ and __array_offset__ */ @@ -8123,12 +8119,118 @@ arraydescr_setstate(PyArray_Descr *self, PyObject *args) } +/* 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: +*/ + +/*OBJECT_API + Deep bytorder change of a data-type descriptor +*/ +static 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->fields) { + PyObject *newfields; + PyObject *key, *value; + PyObject *newvalue; + PyObject *old; + PyArray_Descr *newdescr; + int pos = 0, len, i; + newfields = PyDict_New(); + /* make new dictionary with replaced */ + /* PyArray_Descr Objects */ + while(PyDict_Next(self->fields, &pos, &key, &value)) { + if (PyInt_Check(key) && \ + PyInt_AsLong(key) == -1) { + PyDict_SetItem(newfields, 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 char doc_arraydescr_newbyteorder[] = "self.newbyteorder(<endian>)" + " returns a copy of the dtypedescr object\n" + " with altered byteorders. If <endian> is not given all byteorders\n" + " are swapped. Otherwise endian can be '>', '<', or '=' to force\n" + " a byteorder. Descriptors in all fields are also updated in the\n" + " new dtypedescr object."; + +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, doc_arraydescr_reduce}, {"__setstate__", (PyCFunction)arraydescr_setstate, METH_VARARGS, doc_arraydescr_setstate}, + {"newbyteorder", (PyCFunction)arraydescr_newbyteorder, METH_VARARGS, + doc_arraydescr_newbyteorder}, {NULL, NULL} /* sentinel */ }; diff --git a/scipy/base/src/multiarraymodule.c b/scipy/base/src/multiarraymodule.c index bd4967371..fcdda0f72 100644 --- a/scipy/base/src/multiarraymodule.c +++ b/scipy/base/src/multiarraymodule.c @@ -3453,6 +3453,39 @@ PyArray_DescrConverter(PyObject *obj, PyArray_Descr **at) return PY_FAIL; } +/*MULTIARRAY_API + Convert object to endian +*/ +static int +PyArray_ByteorderConverter(PyObject *obj, char *endian) +{ + char *str; + *endian = PyArray_SWAP; + str = PyString_AsString(obj); + if (!str) return PY_FAIL; + if (strlen(str) < 1) { + PyErr_SetString(PyExc_ValueError, + "Byteorder string must be at least length 1"); + return PY_FAIL; + } + *endian = str[0]; + if (str[0] != PyArray_BIG && str[0] != PyArray_LITTLE && \ + str[0] != PyArray_NATIVE) { + if (str[0] == 'b' || str[0] == 'B') + *endian = PyArray_BIG; + else if (str[0] == 'l' || str[0] == 'L') + *endian = PyArray_LITTLE; + else if (str[0] == 'n' || str[0] == 'N') + *endian = PyArray_NATIVE; + else { + PyErr_Format(PyExc_ValueError, + "%s is an unrecognized byteorder", + str); + return PY_FAIL; + } + } + return PY_SUCCEED; +} /* This function returns true if the two typecodes are equivalent (same basic kind and same itemsize). diff --git a/scipy/base/src/scalartypes.inc.src b/scipy/base/src/scalartypes.inc.src index ac5939450..b127617da 100644 --- a/scipy/base/src/scalartypes.inc.src +++ b/scipy/base/src/scalartypes.inc.src @@ -1032,7 +1032,7 @@ gentype_wraparray(PyObject *scalar, PyObject *args) /**begin repeat -#name=tolist, toscalar, tostring, astype, copy, resize, __deepcopy__, choose, sort, argsort, searchsorted, argmax, argmin, reshape, view, swapaxes, max, min, ptp, conj, conjugate, nonzero, all, any, flatten, ravel, fill, transpose# +#name=tolist, toscalar, tostring, astype, copy, resize, __deepcopy__, choose, sort, argsort, searchsorted, argmax, argmin, reshape, view, swapaxes, max, min, ptp, conj, conjugate, nonzero, all, any, flatten, ravel, fill, transpose, newbyteorder# */ static PyObject * @@ -1102,17 +1102,16 @@ gentype_@name@(PyObject *self, PyObject *args, PyObject *kwds) /**end repeat**/ static PyObject * -voidtype_getfield(PyObject *self, PyObject *args, PyObject *kwds) +voidtype_getfield(PyVoidScalarObject *self, PyObject *args, PyObject *kwds) { PyObject *ret; - ret = gentype_generic_method(self, args, kwds, "getfield"); + ret = gentype_generic_method((PyObject *)self, args, kwds, "getfield"); if (!ret) return ret; if (PyArray_IsScalar(ret, Generic) && \ (!PyArray_IsScalar(ret, Void))) { - PyArray_Descr *descr, *new; - descr = ((PyVoidScalarObject *)self)->descr; - if (!PyArray_ISNBO(descr->byteorder)) { + PyArray_Descr *new; + if (!PyArray_ISNBO(self->descr->byteorder)) { new = PyArray_DescrFromScalar(ret); new->f->copyswap(_SOFFSET_(ret, new->type_num), @@ -1361,7 +1360,8 @@ static PyMethodDef gentype_methods[] = { METH_VARARGS, NULL}, {"setflags", (PyCFunction)gentype_setflags, METH_VARARGS|METH_KEYWORDS, NULL}, - /* add other methods!!! */ + {"newbyteorder", (PyCFunction)gentype_newbyteorder, + METH_VARARGS, NULL}, {NULL, NULL} /* sentinel */ }; |