summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTravis Oliphant <oliphant@enthought.com>2006-01-24 17:33:33 +0000
committerTravis Oliphant <oliphant@enthought.com>2006-01-24 17:33:33 +0000
commit5beecfe93c4755dc18726b8135e79ef06cdfc470 (patch)
tree0cc3c8d271f49e0fd8e2fd85ff9380aa790454ed
parent2718405df3959d6add724e40a7a4d2e6588d8999 (diff)
downloadnumpy-5beecfe93c4755dc18726b8135e79ef06cdfc470.tar.gz
Add ndmin to array constructors.
-rw-r--r--numpy/core/numeric.py8
-rw-r--r--numpy/core/src/arrayobject.c32
-rw-r--r--numpy/core/src/multiarraymodule.c65
-rw-r--r--numpy/lib/shape_base.py14
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, &copy,
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: