diff options
author | Travis Oliphant <oliphant@enthought.com> | 2006-01-24 17:33:33 +0000 |
---|---|---|
committer | Travis Oliphant <oliphant@enthought.com> | 2006-01-24 17:33:33 +0000 |
commit | 5beecfe93c4755dc18726b8135e79ef06cdfc470 (patch) | |
tree | 0cc3c8d271f49e0fd8e2fd85ff9380aa790454ed | |
parent | 2718405df3959d6add724e40a7a4d2e6588d8999 (diff) | |
download | numpy-5beecfe93c4755dc18726b8135e79ef06cdfc470.tar.gz |
Add ndmin to array constructors.
-rw-r--r-- | numpy/core/numeric.py | 8 | ||||
-rw-r--r-- | numpy/core/src/arrayobject.c | 32 | ||||
-rw-r--r-- | numpy/core/src/multiarraymodule.c | 65 | ||||
-rw-r--r-- | numpy/lib/shape_base.py | 14 |
4 files changed, 78 insertions, 41 deletions
diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py index 5e4e0b864..ed6ed0538 100644 --- a/numpy/core/numeric.py +++ b/numpy/core/numeric.py @@ -67,17 +67,17 @@ can_cast = multiarray.can_cast lexsort = multiarray.lexsort -def asarray(a, dtype=None, fortran=False): +def asarray(a, dtype=None, fortran=False, ndmin=0): """returns a as an array. Unlike array(), no copy is performed if a is already an array. Subclasses are converted to base class ndarray. """ - return array(a, dtype, copy=False, fortran=fortran) + return array(a, dtype, copy=False, fortran=fortran, ndmin=ndmin) -def asanyarray(a, dtype=None, copy=False, fortran=False): +def asanyarray(a, dtype=None, copy=False, fortran=False, ndmin=0): """will pass subclasses through... """ - return array(a, dtype, copy=False, fortran=fortran, subok=1) + return array(a, dtype, copy=False, fortran=fortran, subok=1, ndmin=ndmin) def isfortran(a): return a.flags['FNC'] diff --git a/numpy/core/src/arrayobject.c b/numpy/core/src/arrayobject.c index 40cfbafbb..0ab04ce41 100644 --- a/numpy/core/src/arrayobject.c +++ b/numpy/core/src/arrayobject.c @@ -19,7 +19,6 @@ maintainer email: oliphant.travis@ieee.org Numarray design (which provided guidance) by Space Science Telescope Institute (J. Todd Miller, Perry Greenfield, Rick White) - */ /*OBJECT_API @@ -3372,18 +3371,22 @@ PyArray_IntpFromSequence(PyObject *seq, intp *vals, int maxvals) static int _IsContiguous(PyArrayObject *ap) { - intp sd; - int i; + register intp sd; + register intp dim; + register int i; + if (ap->nd == 0) return 1; sd = ap->descr->elsize; - if (ap->nd == 1) return sd == ap->strides[0]; + if (ap->nd == 1) return (ap->dimensions[0] == 1 || \ + sd == ap->strides[0]); for (i = ap->nd-1; i >= 0; --i) { + dim = ap->dimensions[i]; /* contiguous by definition */ - if (ap->dimensions[i] == 0) return 1; - + if (dim == 0) return 1; + if (dim == 1) continue; if (ap->strides[i] != sd) return 0; - sd *= ap->dimensions[i]; + sd *= dim; } return 1; } @@ -3392,18 +3395,21 @@ _IsContiguous(PyArrayObject *ap) static int _IsFortranContiguous(PyArrayObject *ap) { - intp sd; - int i; + register intp sd; + register intp dim; + register int i; if (ap->nd == 0) return 1; sd = ap->descr->elsize; - if (ap->nd == 1) return sd == ap->strides[0]; + if (ap->nd == 1) return (ap->dimensions[0] == 1 || \ + sd == ap->strides[0]); for (i=0; i< ap->nd; ++i) { + dim = ap->dimensions[i]; /* contiguous by definition */ - if (ap->dimensions[i] == 0) return 1; - + if (dim == 0) return 1; + if (dim == 1) continue; if (ap->strides[i] != sd) return 0; - sd *= ap->dimensions[i]; + sd *= dim; } return 1; } diff --git a/numpy/core/src/multiarraymodule.c b/numpy/core/src/multiarraymodule.c index 11f5d7e7d..510adda9d 100644 --- a/numpy/core/src/multiarraymodule.c +++ b/numpy/core/src/multiarraymodule.c @@ -4048,11 +4048,39 @@ PyArray_EquivTypes(PyArray_Descr *typ1, PyArray_Descr *typ2) /*** END C-API FUNCTIONS **/ +static PyObject * +_prepend_ones(PyArrayObject *arr, int nd, int ndmin) +{ + intp newdims[MAX_DIMS]; + intp newstrides[MAX_DIMS]; + int i,k,num; + PyObject *ret; + + num = ndmin-nd; + for (i=0; i<num; i++) { + newdims[i] = 1; + newstrides[i] = arr->descr->elsize; + } + for (i=num;i<ndmin;i++) { + k = i-num; + newdims[i] = arr->dimensions[k]; + newstrides[i] = arr->strides[k]; + } + Py_INCREF(arr->descr); + ret = PyArray_NewFromDescr(arr->ob_type, arr->descr, ndmin, + newdims, newstrides, arr->data, arr->flags, + (PyObject *)arr); + /* steals a reference to arr --- so don't increment + here */ + PyArray_BASE(ret) = (PyObject *)arr; + return ret; +} + #define _ARET(x) PyArray_Return((PyArrayObject *)(x)) static char doc_fromobject[] = "array(object, dtype=None, copy=1, fortran=0, "\ - "subok=0)\n"\ + "subok=0,ndmin=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"\ @@ -4062,27 +4090,32 @@ static char doc_fromobject[] = "array(object, dtype=None, copy=1, fortran=0, "\ "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"; + "array may be returned. Otherwise, a base-class ndarray is returned\n"\ + "The ndmin argument specifies how many dimensions the returned\n"\ + "array should have as a minimum. 1's will be pre-pended to the\n"\ + "shape as needed to meet this requirement."; static PyObject * _array_fromobject(PyObject *ignored, PyObject *args, PyObject *kws) { PyObject *op, *ret=NULL; - static char *kwd[]= {"object", "dtype", "copy", "fortran", "subok", /* XXX ? */ - NULL}; + static char *kwd[]= {"object", "dtype", "copy", "fortran", "subok", + "ndmin", NULL}; Bool subok=FALSE; Bool copy=TRUE; + int ndmin=0, nd; PyArray_Descr *type=NULL; PyArray_Descr *oldtype=NULL; Bool fortran=FALSE; int flags=0; - if(!PyArg_ParseTupleAndKeywords(args, kws, "O|O&O&O&O&", kwd, &op, + if(!PyArg_ParseTupleAndKeywords(args, kws, "O|O&O&O&O&i", kwd, &op, PyArray_DescrConverter2, &type, PyArray_BoolConverter, ©, PyArray_BoolConverter, &fortran, - PyArray_BoolConverter, &subok)) + PyArray_BoolConverter, &subok, + &ndmin)) return NULL; /* fast exit if simple call */ @@ -4090,11 +4123,13 @@ _array_fromobject(PyObject *ignored, PyObject *args, PyObject *kws) if (type==NULL) { if (!copy && fortran==PyArray_ISFORTRAN(op)) { Py_INCREF(op); - return op; + ret = op; + goto finish; } else { - return PyArray_NewCopy((PyArrayObject*)op, - fortran); + ret = PyArray_NewCopy((PyArrayObject*)op, + fortran); + goto finish; } } /* One more chance */ @@ -4102,7 +4137,8 @@ _array_fromobject(PyObject *ignored, PyObject *args, PyObject *kws) if (PyArray_EquivTypes(oldtype, type)) { if (!copy && fortran==PyArray_ISFORTRAN(op)) { Py_INCREF(op); - return op; + ret = op; + goto finish; } else { ret = PyArray_NewCopy((PyArrayObject*)op, @@ -4111,7 +4147,7 @@ _array_fromobject(PyObject *ignored, PyObject *args, PyObject *kws) Py_INCREF(oldtype); Py_DECREF(PyArray_DESCR(ret)); PyArray_DESCR(ret) = oldtype; - return ret; + goto finish; } } } @@ -4129,7 +4165,12 @@ _array_fromobject(PyObject *ignored, PyObject *args, PyObject *kws) if ((ret = PyArray_CheckFromAny(op, type, 0, 0, flags, NULL)) == NULL) return NULL; - return ret; + finish: + + if ((nd=PyArray_NDIM(ret)) >= ndmin) return ret; + /* create a new array from the same data with ones in the shape */ + /* steals a reference to ret */ + return _prepend_ones((PyArrayObject *)ret, nd, ndmin); } /* accepts NULL type */ diff --git a/numpy/lib/shape_base.py b/numpy/lib/shape_base.py index 0515a74ab..74d763821 100644 --- a/numpy/lib/shape_base.py +++ b/numpy/lib/shape_base.py @@ -120,10 +120,7 @@ def atleast_1d(*arys): """ res = [] for ary in arys: - ary = asarray(ary) - if len(ary.shape) == 0: - ary = ary.reshape(1) - res.append(ary) + res.append(asarray(ary,ndmin=1)) if len(res) == 1: return res[0] else: @@ -143,14 +140,7 @@ def atleast_2d(*arys): """ res = [] for ary in arys: - ary = asarray(ary) - if len(ary.shape) == 0: - result = ary.reshape(1,1) - elif len(ary.shape) == 1: - result = ary[newaxis,:] - else: - result = ary - res.append(result) + res.append(asarray(ary,ndmin=2)) if len(res) == 1: return res[0] else: |