diff options
-rw-r--r-- | scipy/base/include/scipy/arrayobject.h | 23 | ||||
-rw-r--r-- | scipy/base/matrix.py | 2 | ||||
-rw-r--r-- | scipy/base/numeric.py | 38 | ||||
-rw-r--r-- | scipy/base/src/arrayobject.c | 62 | ||||
-rw-r--r-- | scipy/base/src/multiarraymodule.c | 30 | ||||
-rw-r--r-- | scipy/base/src/umathmodule.c.src | 35 |
6 files changed, 125 insertions, 65 deletions
diff --git a/scipy/base/include/scipy/arrayobject.h b/scipy/base/include/scipy/arrayobject.h index f28af0eaf..48b899a4b 100644 --- a/scipy/base/include/scipy/arrayobject.h +++ b/scipy/base/include/scipy/arrayobject.h @@ -811,28 +811,23 @@ typedef struct { it is also FORTRAN contiguous */ - /* Not used -- always assumed -#define OWN_DIMENSIONS 2 -#define OWN_STRIDES 4 - */ +#define FORTRAN 2 /* set if array is a contiguous Fortran array */ + /* first index varies the fastest in memory + (strides array is reverse of C-contiguous + array)*/ -#define OWNDATA 8 +#define OWNDATA 4 #define OWN_DATA OWNDATA -#define FORTRAN 0x020 /* set if array is a contiguous Fortran array */ - /* first index varies the fastest in memory - (strides array is reverse of C-contiguous - array)*/ - - /* array never has these two set -- FromAny flags only */ -#define FORCECAST 0x040 -#define ENSURECOPY 0x080 + /* array never has these three set -- FromAny flags only */ +#define FORCECAST 0x010 +#define ENSURECOPY 0x020 +#define ENSUREARRAY 0x040 #define ALIGNED 0x100 #define NOTSWAPPED 0x200 #define WRITEABLE 0x400 - /* Flag used in creating a new array, not set in the array */ /* If this flags is set, then base contains a pointer to an array of the same size that should be updated with the diff --git a/scipy/base/matrix.py b/scipy/base/matrix.py index 6fc717cb7..721dfc8ce 100644 --- a/scipy/base/matrix.py +++ b/scipy/base/matrix.py @@ -84,7 +84,7 @@ class matrix(N.ndarray): ret = N.ndarray.__new__(matrix, shape, arr.dtype, buffer=arr, fortran=fortran, - swap=(not arr.flags['NOTSWAPPED'])) + swap=arr.flags['S']) return ret; diff --git a/scipy/base/numeric.py b/scipy/base/numeric.py index 931a6cfff..77edcdf99 100644 --- a/scipy/base/numeric.py +++ b/scipy/base/numeric.py @@ -27,35 +27,17 @@ fastCopyAndTranspose = multiarray._fastCopyAndTranspose register_dtype = multiarray.register_dtype can_cast = multiarray.can_cast - def asarray(a, dtype=None): """asarray(a,dtype=None) returns a as an array. Unlike array(), - no copy is performed if a is already an array. Will return a subclass - of array. + no copy is performed if a is already an array. Subclasses are converted + to base class ndarray. """ return array(a, dtype, copy=0) -def asndarray(a, dtype=None): - """asndarray(a, dtype=None) always returns an actual ndarray object. - No copy is performed if a is already an array. - Meant primarily for debugging. +def asanyarray(a, dtype=None): + """will pass subclasses through... """ - dtype = obj2dtype(dtype) - # exact check - while 1: - if type(a) is ndarray: - if dtype is None or a.dtype is dtype: - return a - else: - return a.astype(dtype) - try: - if dtype is None: - return a.__array__() - else: - return a.__array__(dtype) - except AttributeError: - a = array(a,dtype) # copy irrelevant - dtype = None + return array(a, dtype, copy=0, subok=1) def isfortran(a): return a.flags['FNC'] @@ -66,9 +48,9 @@ def zeros_like(a): If you don't explicitly need the array to be zeroed, you should instead use empty_like(), which is faster as it only allocates memory.""" - - a = asarray(a) - return zeros(a.shape,a.dtype, a.flags['FNC']) + + a = asanyarray(a) + return a.__array_wrap__(zeros(a.shape,a.dtype, a.flags['FNC'])) def empty_like(a): """Return an empty (uninitialized) array of the shape and typecode of a. @@ -77,8 +59,8 @@ def empty_like(a): your array to be initialized, you should use zeros_like(). """ - a = asarray(a) - return empty(a.shape,a.dtype, a.flags['FNC']) + a = asanyarray(a) + return a.__array_wrap__(empty(a.shape,a.dtype, a.flags['FNC'])) # end Fernando's utilities diff --git a/scipy/base/src/arrayobject.c b/scipy/base/src/arrayobject.c index 305bf46bf..78f753040 100644 --- a/scipy/base/src/arrayobject.c +++ b/scipy/base/src/arrayobject.c @@ -3532,8 +3532,8 @@ array_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds) return PyArray_Return(ret); fail: - if (dims.ptr) free(dims.ptr); - if (strides.ptr) free(strides.ptr); + if (dims.ptr) PyDimMem_FREE(dims.ptr); + if (strides.ptr) PyDimMem_FREE(strides.ptr); return NULL; } @@ -4857,7 +4857,7 @@ PyArray_CastToType(PyArrayObject *mp, PyArray_Typecode *at) PyObject *out; int ret; - if ((mp->descr->type_num == at->type_num) && \ + if ((mp->descr->type_num == at->type_num) && \ (at->itemsize==0 || mp->itemsize == at->itemsize) && PyArray_ISBEHAVED_RO(mp)) { Py_INCREF(mp); @@ -4953,11 +4953,14 @@ array_fromarray(PyArrayObject *arr, PyArray_Typecode *typecode, int flags) int arrflags; PyArray_Typecode oldtype; char *msg = "Cannot copy-back to a read-only array."; + PyTypeObject *subtype; oldtype.type_num = PyArray_TYPE(arr); oldtype.itemsize = PyArray_ITEMSIZE(arr); oldtype.fortran = 0; + subtype = arr->ob_type; + if (type == PyArray_NOTYPE) type = arr->descr->type_num; if (itemsize == 0) itemsize = arr->itemsize; typecode->type_num = type; @@ -4982,8 +4985,12 @@ array_fromarray(PyArrayObject *arr, PyArray_Typecode *typecode, int flags) PyErr_SetString(PyExc_ValueError, msg); return NULL; } - ret = (PyArrayObject *)\ - PyArray_New(arr->ob_type, + if ((flags & ENSUREARRAY) && \ + (subtype != &PyBigArray_Type)) { + subtype = &PyArray_Type; + } + ret = (PyArrayObject *) \ + PyArray_New(subtype, arr->nd, arr->dimensions, arr->descr->type_num, @@ -5002,8 +5009,25 @@ array_fromarray(PyArrayObject *arr, PyArray_Typecode *typecode, int flags) /* If no copy then just increase the reference count and return the input */ else { + if ((flags & ENSUREARRAY) && \ + (subtype != &PyBigArray_Type)) { + ret = (PyArrayObject *) \ + PyArray_New(&PyArray_Type, + arr->nd, + arr->dimensions, + arr->descr->type_num, + arr->strides, + arr->data, + arr->itemsize, + arr->flags,NULL); + if (ret == NULL) return NULL; + ret->base = (PyObject *)arr; + ret->flags &= ~UPDATEIFCOPY; + } + else { + ret = arr; + } Py_INCREF(arr); - ret = arr; } } @@ -5020,8 +5044,21 @@ array_fromarray(PyArrayObject *arr, PyArray_Typecode *typecode, int flags) PyErr_SetString(PyExc_ValueError, msg); return NULL; } - ret = (PyArrayObject *)\ - PyArray_CastToType(arr, typecode); + if ((flags & ENSUREARRAY) && \ + (subtype != &PyBigArray_Type)) { + subtype = &PyArray_Type; + } + ret = (PyArrayObject *)\ + PyArray_New(subtype, arr->nd, + arr->dimensions, typecode->type_num, + NULL, NULL, typecode->itemsize, + typecode->fortran, + (PyObject *)arr); + if (ret == NULL) return NULL; + if (PyArray_CastTo(ret, arr) < 0) { + Py_DECREF(ret); + return NULL; + } if (flags & UPDATEIFCOPY) { ret->flags |= UPDATEIFCOPY; ret->base = (PyObject *)arr; @@ -5031,7 +5068,7 @@ array_fromarray(PyArrayObject *arr, PyArray_Typecode *typecode, int flags) } else { PyErr_SetString(PyExc_TypeError, - "Array can not be safely cast "\ + "Array can not be safely cast " \ "to required type"); ret = NULL; } @@ -5440,6 +5477,7 @@ PyArray_FromAny(PyObject *op, PyArray_Typecode *typecode, int min_depth, /* This is a quick wrapper around PyArray_FromAny(op, NULL, 0, 0, 0) */ /* that special cases Arrays and PyArray_Scalars up front */ /* It steals a reference to the object */ +/* It also guarantees that the result is PyArray_Type or PyBigArray_Type */ /* Because it decrefs op if any conversion needs to take place -- so it can be used like PyArray_EnsureArray(some_function(...)) */ @@ -5451,14 +5489,14 @@ PyArray_EnsureArray(PyObject *op) if (op == NULL) return NULL; - if (PyArray_Check(op)) return op; - + if (PyArray_CheckExact(op) || PyBigArray_CheckExact(op)) return op; + if (PyArray_IsScalar(op, Generic)) { new = PyArray_FromScalar(op, NULL); Py_DECREF(op); return new; } - new = PyArray_FromAny(op, NULL, 0, 0, 0); + new = PyArray_FromAny(op, NULL, 0, 0, ENSUREARRAY); Py_DECREF(op); return new; } diff --git a/scipy/base/src/multiarraymodule.c b/scipy/base/src/multiarraymodule.c index eb85c10fe..1f2069766 100644 --- a/scipy/base/src/multiarraymodule.c +++ b/scipy/base/src/multiarraymodule.c @@ -2809,13 +2809,26 @@ PyArray_EquivArrTypes(PyArrayObject *a1, PyArrayObject *a2) #define _ARET(x) PyArray_Return((PyArrayObject *)(x)) -static char doc_fromobject[] = "array(object, dtype=None, copy=1, fortran=0) will return a new array formed from the given object type given. Object can anything with an __array__ method, or any (nested) sequence. If no type is given, then the type will be determined as the minimum type required to hold the objects in the sequence. If copy is zero and sequence is already an array with the right type, a reference will be returned. If the sequence is an array, type can be used only to upcast the array. For downcasting use .astype(t) method."; +static char doc_fromobject[] = "array(object, dtype=None, copy=1, fortran=0, "\ + "subok=0)\n"\ + "will return a new array formed from the given object type given.\n"\ + "Object can anything with an __array__ method, or any object\n"\ + "exposing the array interface, or any (nested) sequence.\n"\ + "If no type is given, then the type will be determined as the\n"\ + "minimum type required to hold the objects in the sequence.\n"\ + "If copy is zero and sequence is already an array with the right \n"\ + "type, a reference will be returned. If the sequence is an array,\n"\ + "type can be used only to upcast the array. For downcasting \n"\ + "use .astype(t) method. If subok is true, then subclasses of the\n"\ + "array may be returned. Otherwise, a base-class ndarray is returned"; static PyObject * _array_fromobject(PyObject *ignored, PyObject *args, PyObject *kws) { PyObject *op, *ret=NULL; - static char *kwd[]= {"object", "dtype", "copy", "fortran", NULL}; + static char *kwd[]= {"object", "dtype", "copy", "fortran", "subok", + NULL}; + Bool subok=FALSE; Bool copy=TRUE; PyArray_Typecode type = {PyArray_NOTYPE, 0, 0}; PyArray_Typecode oldtype = {PyArray_NOTYPE, 0, 0}; @@ -2823,16 +2836,18 @@ _array_fromobject(PyObject *ignored, PyObject *args, PyObject *kws) Bool fortran=FALSE; int flags=0; - if(!PyArg_ParseTupleAndKeywords(args, kws, "O|O&O&O&", kwd, &op, + if(!PyArg_ParseTupleAndKeywords(args, kws, "O|O&O&O&O&", kwd, &op, PyArray_TypecodeConverter, &type, PyArray_BoolConverter, ©, - PyArray_BoolConverter, &fortran)) + PyArray_BoolConverter, &fortran, + PyArray_BoolConverter, &subok)) return NULL; type_num = type.type_num; /* fast exit if simple call */ - if (PyArray_Check(op) && (copy==0) && \ + if ((PyArray_CheckExact(op) && PyBigArray_CheckExact(op)) && \ + (copy==0) && \ (fortran == PyArray_CHKFLAGS(op, FORTRAN))) { if (type_num == PyArray_NOTYPE) { Py_INCREF(op); @@ -2851,11 +2866,14 @@ _array_fromobject(PyObject *ignored, PyObject *args, PyObject *kws) if (copy) { flags = ENSURECOPY; } + if (!subok) { + flags |= ENSUREARRAY; + } if ((ret = PyArray_FromAny(op, &type, 0, 0, flags)) == NULL) return NULL; - return _ARET(ret); + return ret; } static PyObject * diff --git a/scipy/base/src/umathmodule.c.src b/scipy/base/src/umathmodule.c.src index 1dcac383b..700d918ea 100644 --- a/scipy/base/src/umathmodule.c.src +++ b/scipy/base/src/umathmodule.c.src @@ -1378,10 +1378,10 @@ static void /**begin repeat -#TYPE=(BOOL,BYTE,UBYTE,SHORT,USHORT,INT,UINT,LONG,ULONG,LONGLONG,ULONGLONG,FLOAT,DOUBLE,LONGDOUBLE,CFLOAT,CDOUBLE,CLONGDOUBLE)*2# -#OP= >*17, <*17# -#typ=(Bool, byte, ubyte, short, ushort, int, uint, long, ulong, longlong, ulonglong, float, double, longdouble, float, double, longdouble)*2# -#kind= maximum*17, minimum*17# +#TYPE=(BOOL,BYTE,UBYTE,SHORT,USHORT,INT,UINT,LONG,ULONG,LONGLONG,ULONGLONG,FLOAT,DOUBLE,LONGDOUBLE)*2# +#OP= >*14, <*14# +#typ=(Bool, byte, ubyte, short, ushort, int, uint, long, ulong, longlong, ulonglong, float, double, longdouble)*2# +#kind= maximum*14, minimum*14# */ static void @TYPE@_@kind@(char **args, intp *dimensions, intp *steps, void *func) @@ -1395,6 +1395,33 @@ static void } /**end repeat**/ +/**begin repeat + +#TYPE=(CFLOAT,CDOUBLE,CLONGDOUBLE)*2# +#OP= >*3, <*3# +#typ=(cfloat, cdouble, clongdouble)*2# +#kind= maximum*3, minimum*3# +*/ +static void +@TYPE@_@kind@(char **args, intp *dimensions, intp *steps, void *func) +{ + register intp i; + intp is1=steps[0],is2=steps[1],os=steps[2], n=dimensions[0]; + char *i1=args[0], *i2=args[1], *op=args[2]; + @typ@ *i1c, *i2c; + for(i=0; i<n; i++, i1+=is1, i2+=is2, op+=os) { + i1c = (@typ@ *)i1; + i2c = (@typ@ *)i2; + if ((i1c->real @OP@ i2c->real) || \ + ((i1c->real==i2c->real) && (i1c->imag @OP@ i2c->imag))) + memcpy(op, i1, sizeof(@typ@)); + else + memcpy(op, i2, sizeof(@typ@)); + } +} +/**end repeat**/ + + /*** isinf, isinf, isfinite, signbit ***/ /**begin repeat |