diff options
author | Travis Oliphant <oliphant@enthought.com> | 2005-12-14 22:03:04 +0000 |
---|---|---|
committer | Travis Oliphant <oliphant@enthought.com> | 2005-12-14 22:03:04 +0000 |
commit | 9985d7cc7892effbe9290002ef3613ea33e02179 (patch) | |
tree | 3b5cc3f0b3bb1094e420e3a705fa578d2ab006ec | |
parent | 9df62b0d2072bfa5809c21a4e181b3a186317422 (diff) | |
download | numpy-9985d7cc7892effbe9290002ef3613ea33e02179.tar.gz |
Added newbyteorder methods.
-rw-r--r-- | scipy/base/chararray.py | 5 | ||||
-rw-r--r-- | scipy/base/code_generators/array_api_order.txt | 1 | ||||
-rw-r--r-- | scipy/base/code_generators/multiarray_api_order.txt | 1 | ||||
-rw-r--r-- | scipy/base/include/scipy/arrayobject.h | 21 | ||||
-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 | ||||
-rw-r--r-- | scipy/core_version.py | 2 | ||||
-rw-r--r-- | scipy/doc/CAPI.txt | 18 |
10 files changed, 198 insertions, 37 deletions
diff --git a/scipy/base/chararray.py b/scipy/base/chararray.py index 58b874827..c7edcd4bd 100644 --- a/scipy/base/chararray.py +++ b/scipy/base/chararray.py @@ -1,6 +1,7 @@ from numerictypes import character, string, unicode_, \ obj2dtype, integer, object_ -from numeric import ndarray, broadcast, empty, array +from numeric import ndarray, broadcast, empty +from numeric import array as narray import sys __all__ = ['chararray'] @@ -316,7 +317,7 @@ def array(obj, itemlen=7, copy=True, unicode=False, fortran=False): else: dtype = "S%d" % itemlen - val = array(obj, dtype=dtype, fortran=fortran, subok=1) + val = narray(obj, dtype=dtype, fortran=fortran, subok=1) return chararray(val.shape, itemlen, unicode, buffer=val, strides=val.strides, diff --git a/scipy/base/code_generators/array_api_order.txt b/scipy/base/code_generators/array_api_order.txt index c2750ace4..3dfd848a0 100644 --- a/scipy/base/code_generators/array_api_order.txt +++ b/scipy/base/code_generators/array_api_order.txt @@ -58,3 +58,4 @@ PyArray_Broadcast PyArray_FillObjectArray PyArray_FillWithScalar PyArray_CheckStrides +PyArray_DescrNewByteorder diff --git a/scipy/base/code_generators/multiarray_api_order.txt b/scipy/base/code_generators/multiarray_api_order.txt index e97dfbd27..65a313428 100644 --- a/scipy/base/code_generators/multiarray_api_order.txt +++ b/scipy/base/code_generators/multiarray_api_order.txt @@ -55,6 +55,7 @@ PyArray_IntpConverter PyArray_BufferConverter PyArray_AxisConverter PyArray_BoolConverter +PyArray_ByteorderConverter PyArray_EquivalentTypes PyArray_Zeros PyArray_Empty diff --git a/scipy/base/include/scipy/arrayobject.h b/scipy/base/include/scipy/arrayobject.h index 5023631b0..348027689 100644 --- a/scipy/base/include/scipy/arrayobject.h +++ b/scipy/base/include/scipy/arrayobject.h @@ -1212,17 +1212,22 @@ typedef struct { #define PyArray_ISEXTENDED(obj) PyTypeNum_ISEXTENDED(PyArray_TYPE(obj)) #define PyArray_ISOBJECT(obj) PyTypeNum_ISOBJECT(PyArray_TYPE(obj)) +#define PyArray_LITTLE '<' +#define PyArray_BIG '>' +#define PyArray_NATIVE '=' +#define PyArray_SWAP 's' +#define PyArray_IGNORE '|' + #ifdef WORDS_BIGENDIAN -#define PyArray_NATIVEBYTE '>' -#define PyArray_OPPOSITEBYTE '<' -#define PyArray_IsNativeByteOrder(byteorder) (byteorder != '<') -#define PyArray_ISNBO(byteorder) (byteorder != '<') +#define PyArray_NATBYTE PyArray_BIG +#define PyArray_OPPBYTE PyArray_LITTLE #else -#define PyArray_NATIVEBYTE '<' -#define PyArray_OPPOSITEBYTE '>' -#define PyArray_IsNativeByteOrder(byteorder) (byteorder != '>') -#define PyArray_ISNBO(byteorder) (byteorder != '>') +#define PyArray_NATBYTE PyArray_LITTLE +#define PyArray_OPPBYTE PyArray_BIG #endif + +#define PyArray_ISNBO(arg) ((arg) != PyArray_OPPBYTE) +#define PyArray_IsNativeByteOrder PyArray_ISNBO #define PyArray_ISNOTSWAPPED(m) PyArray_ISNBO(PyArray_DESCR(m)->byteorder) #define PyArray_FLAGSWAP(m, flags) (PyArray_CHKFLAGS(m, flags) && \ 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 */ }; diff --git a/scipy/core_version.py b/scipy/core_version.py index 3a1f3887a..754a70e6a 100644 --- a/scipy/core_version.py +++ b/scipy/core_version.py @@ -1,4 +1,4 @@ -version='0.8.5' +version='0.8.6' import os svn_version_file = os.path.join(os.path.dirname(__file__), diff --git a/scipy/doc/CAPI.txt b/scipy/doc/CAPI.txt index 1142ce7e2..f8bfd3981 100644 --- a/scipy/doc/CAPI.txt +++ b/scipy/doc/CAPI.txt @@ -164,7 +164,6 @@ requires can be any of CONTIGUOUS, FORTRAN, ALIGNED, - NOTSWAPPED, WRITEABLE, ENSURECOPY, ENSUREARRAY, @@ -178,11 +177,11 @@ requires can be any of won't guarantee it -- it will depend on the object as to whether or not it has such features. - Note that ENSURECOPY is enough to guarantee CONTIGUOUS, ALIGNED, NOTSWAPPED, + Note that ENSURECOPY is enough to guarantee CONTIGUOUS, ALIGNED, and WRITEABLE and therefore it is redundant to include those as well. - BEHAVED_FLAGS == ALIGNED | NOTSWAPPED | WRITEABLE - BEHAVED_FLAGS_RO == ALIGNED | NOTSWAPPED + BEHAVED_FLAGS == ALIGNED | WRITEABLE + BEHAVED_FLAGS_RO == ALIGNED CARRAY_FLAGS = CONTIGUOUS | BEHAVED_FLAGS FARRAY_FLAGS = FORTRAN | BEHAVED_FLAGS @@ -276,9 +275,6 @@ array, or part of some larger record array. But, they may have other uses... ALIGNED : True if the data buffer is aligned for the type. This can be checked. -NOTSWAPPED : True if the data is in machine byte order. Arrays - can be out of machine byte order and will still - work (albeit more slowly). WRITEABLE : True only if the data buffer can be "written" to. @@ -302,16 +298,18 @@ PyArray_UpdateFlags(obj, FLAGS) will update the obj->flags for FLAGS Some useful combinations of these flags: -BEHAVED = ALIGNED | NOTSWAPPED | WRITEABLE -BEHAVED_RO = ALIGNED | NOTSWAPPED +BEHAVED = ALIGNED | WRITEABLE +BEHAVED_RO = ALIGNED CARRAY_FLAGS = CONTIGUOUS | BEHAVED FARRAY_FLAGS = FORTRAN | BEHAVED - The macro PyArray_CHECKFLAGS(obj, FLAGS) can test any combination of flags. There are several default combinations defined as macros already (see arrayobject.h) +In particular, there are ISBEHAVED, ISBEHAVED_RO, ISCARRAY and ISFARRAY macros +that also check to make sure the array is in native byte order (as determined) +by the data-type descriptor. There are more C-API enhancements which you can discover in the code, or buy the book (http://www.trelgol.com) |