[Numpy-svn] r3353 - in trunk/numpy/core: . include/numpy src

numpy-svn at scipy.org numpy-svn at scipy.org
Tue Oct 17 19:53:55 EDT 2006


Author: oliphant
Date: 2006-10-17 18:53:52 -0500 (Tue, 17 Oct 2006)
New Revision: 3353

Modified:
   trunk/numpy/core/include/numpy/ndarrayobject.h
   trunk/numpy/core/numeric.py
   trunk/numpy/core/src/ufuncobject.c
Log:
Increase the C-API and allow ufuncs to be given keyword arguments.  Re-compile extension modules after updating to this revision number.  extobj= and dtype= keywords are possible, but only extobj= is implemented in this revision.

Modified: trunk/numpy/core/include/numpy/ndarrayobject.h
===================================================================
--- trunk/numpy/core/include/numpy/ndarrayobject.h	2006-10-17 21:43:08 UTC (rev 3352)
+++ trunk/numpy/core/include/numpy/ndarrayobject.h	2006-10-17 23:53:52 UTC (rev 3353)
@@ -30,7 +30,7 @@
 #define NPY_SUCCEED 1
 
         /* Helpful to distinguish what is installed */
-#define NPY_VERSION 0x01000002
+#define NPY_VERSION 0x01000008
 
         /* Some platforms don't define bool, long long, or long double.
            Handle that here.

Modified: trunk/numpy/core/numeric.py
===================================================================
--- trunk/numpy/core/numeric.py	2006-10-17 21:43:08 UTC (rev 3352)
+++ trunk/numpy/core/numeric.py	2006-10-17 23:53:52 UTC (rev 3353)
@@ -156,16 +156,11 @@
         return asanyarray(a, dtype=dtype)
 
     if 'ENSUREARRAY' in requirements or 'E' in requirements:
-        func = asarray
+        subok = 0
     else:
-        func = asanyarray
+        subok = 1
 
-    if 'FORCECAST' in requirements or 'FORCE' in requirements:
-        arr = func(a)
-        if dtype is not None and arr.dtype != dtype:
-            arr = arr.astype(dtype)
-    else:
-        arr = func(a, dtype=dtype)
+    arr = array(a, dtype=dtype, copy=False, subok=subok)
 
     copychar = 'A'
     if 'FORTRAN' in requirements or 'F' in requirements:
@@ -180,7 +175,7 @@
     return arr   
 
 def isfortran(a):
-    """Returns True if 'a' is laid out in Fortran-order in memory.
+    """Returns True if 'a' is laid out in Fortran-order in memory (and a.ndim > 1)
     """
     return a.flags.fnc
 

Modified: trunk/numpy/core/src/ufuncobject.c
===================================================================
--- trunk/numpy/core/src/ufuncobject.c	2006-10-17 21:43:08 UTC (rev 3352)
+++ trunk/numpy/core/src/ufuncobject.c	2006-10-17 23:53:52 UTC (rev 3353)
@@ -664,12 +664,19 @@
 static int
 select_types(PyUFuncObject *self, int *arg_types,
              PyUFuncGenericFunction *function, void **data,
-	     PyArray_SCALARKIND *scalars)
+	     PyArray_SCALARKIND *scalars,
+             PyArray_Descr *dtype)
 {
 	int i, j;
 	char start_type;
 	int userdef=-1;
 
+        /*
+          if (dtype != NULL)
+          return extract_specified_loop(self, arg_types, function, data,
+          scalars, dtype)
+        */
+
 	if (self->userloops) {
 		for (i=0; i<self->nin; i++) {
 			if (PyTypeNum_ISUSERDEF(arg_types[i])) {
@@ -745,37 +752,11 @@
 static PyObject *PyUFunc_PYVALS_NAME=NULL;
 
 
-/*UFUNC_API*/
 static int
-PyUFunc_GetPyValues(char *name, int *bufsize, int *errmask, PyObject **errobj)
+_extract_pyvals(PyObject *ref, char *name, int *bufsize, int *errmask, PyObject **errobj)
 {
-        PyObject *thedict;
-        PyObject *ref=NULL;
-	PyObject *retval;
+        PyObject *retval;
 
-        #if USE_USE_DEFAULTS==1
-	if (PyUFunc_NUM_NODEFAULTS != 0) {
-        #endif
-		if (PyUFunc_PYVALS_NAME == NULL) {
-			PyUFunc_PYVALS_NAME = \
-				PyString_InternFromString(UFUNC_PYVALS_NAME);
-		}
-		thedict = PyThreadState_GetDict();
-		if (thedict == NULL) {
-			thedict = PyEval_GetBuiltins();
-		}
-		ref = PyDict_GetItem(thedict, PyUFunc_PYVALS_NAME);
-        #if USE_USE_DEFAULTS==1
-	}
-        #endif
-	if (ref == NULL) {
-		*errmask = UFUNC_ERR_DEFAULT;
-		*errobj = Py_BuildValue("NO",
-					PyString_FromString(name),
-					Py_None);
-		*bufsize = PyArray_BUFSIZE;
-		return 0;
-	}
 	*errobj = NULL;
 	if (!PyList_Check(ref) || (PyList_GET_SIZE(ref)!=3)) {
 		PyErr_Format(PyExc_TypeError, "%s must be a length 3 list.",
@@ -820,6 +801,41 @@
 	return 0;
 }
 
+
+
+/*UFUNC_API*/
+static int
+PyUFunc_GetPyValues(char *name, int *bufsize, int *errmask, PyObject **errobj)
+{
+        PyObject *thedict;
+        PyObject *ref=NULL;
+
+        #if USE_USE_DEFAULTS==1
+	if (PyUFunc_NUM_NODEFAULTS != 0) {
+        #endif
+		if (PyUFunc_PYVALS_NAME == NULL) {
+			PyUFunc_PYVALS_NAME = \
+				PyString_InternFromString(UFUNC_PYVALS_NAME);
+		}
+		thedict = PyThreadState_GetDict();
+		if (thedict == NULL) {
+			thedict = PyEval_GetBuiltins();
+		}
+		ref = PyDict_GetItem(thedict, PyUFunc_PYVALS_NAME);
+        #if USE_USE_DEFAULTS==1
+	}
+        #endif
+	if (ref == NULL) {
+		*errmask = UFUNC_ERR_DEFAULT;
+		*errobj = Py_BuildValue("NO",
+					PyString_FromString(name),
+					Py_None);
+		*bufsize = PyArray_BUFSIZE;
+		return 0;
+	}
+        return _extract_pyvals(ref, name, bufsize, errmask, errobj);
+}
+
 /* Create copies for any arrays that are less than loop->bufsize
    in total size and are mis-behaved or in need
    of casting.
@@ -891,7 +907,8 @@
 #undef _GETATTR_
 
 static int
-construct_arrays(PyUFuncLoopObject *loop, PyObject *args, PyArrayObject **mps)
+construct_arrays(PyUFuncLoopObject *loop, PyObject *args, PyArrayObject **mps,
+                 PyArray_Descr *dtype)
 {
         int nargs, i, maxsize;
         int arg_types[NPY_MAXARGS];
@@ -959,13 +976,13 @@
 
         /* Select an appropriate function for these argument types. */
         if (select_types(loop->ufunc, arg_types, &(loop->function),
-                         &(loop->funcdata), scalars) == -1)
+                         &(loop->funcdata), scalars, dtype) == -1)
 		return -1;
 
         /* FAIL with NotImplemented if the other object has
 	   the __r<op>__ method and has __array_priority__ as
 	   an attribute (signalling it can handle ndarray's)
-	   and is not already an ndarray or bigndarray
+	   and is not already an ndarray
 	*/
         if ((arg_types[1] == PyArray_OBJECT) &&				\
             (loop->ufunc->nin==2) && (loop->ufunc->nout == 1)) {
@@ -1355,10 +1372,13 @@
 }
 
 static PyUFuncLoopObject *
-construct_loop(PyUFuncObject *self, PyObject *args, PyArrayObject **mps)
+construct_loop(PyUFuncObject *self, PyObject *args, PyObject *kwds, PyArrayObject **mps)
 {
 	PyUFuncLoopObject *loop;
 	int i;
+        PyArray_Descr *dtype=NULL;
+        PyObject *extobj=NULL;
+        char *name;
 
 	if (self == NULL) {
 		PyErr_SetString(PyExc_ValueError, "function not supported");
@@ -1379,12 +1399,48 @@
 	loop->errobj = NULL;
         loop->notimplemented = 0;
 
-	if (PyUFunc_GetPyValues((self->name ? self->name : ""),
-				&(loop->bufsize), &(loop->errormask),
-				&(loop->errobj)) < 0) goto fail;
 
+        /* Extract dtype= keyword and
+           extobj= keyword if present
+           Raise an error if anything else present in the keyword dictionary
+        */
+        if (kwds != NULL) {
+                PyObject *key, *value;
+                Py_ssize_t pos;
+                while (PyDict_Next(kwds, &pos, &key, &value)) {
+                        if (!PyString_Check(key)) {
+                                PyErr_SetString(PyExc_TypeError, "invalid keyword");
+                                goto fail;
+                        }
+                        if (strncmp(PyString_AS_STRING(key), "extobj", 6) == 0) {
+                                extobj = value;
+                        }
+                        else if (strncmp(PyString_AS_STRING(key), "dtype", 5) == 0) {
+                                if (PyArray_DescrConverter2(value, &dtype) == PY_FAIL)
+                                        goto fail;
+                        }
+                        else {
+                                PyErr_Format(PyExc_TypeError, "'%s' is an invalid keyword",
+                                             PyString_AS_STRING(key));
+                                goto fail;
+                        }
+                }
+        }
+
+        name = self->name ? self->name : "";
+        if (extobj == NULL) {
+                if (PyUFunc_GetPyValues(name,
+                                        &(loop->bufsize), &(loop->errormask),
+                                        &(loop->errobj)) < 0) goto fail;
+        }
+        else {
+                if (_extract_pyvals(extobj, name,
+                                    &(loop->bufsize), &(loop->errormask),
+                                    &(loop->errobj)) < 0) goto fail;
+        }
+        
 	/* Setup the arrays */
-	if (construct_arrays(loop, args, mps) < 0) goto fail;
+	if (construct_arrays(loop, args, mps, dtype) < 0) goto fail;
 
 	PyUFunc_clearfperr();
 
@@ -1465,14 +1521,14 @@
 
 /*UFUNC_API*/
 static int
-PyUFunc_GenericFunction(PyUFuncObject *self, PyObject *args,
+PyUFunc_GenericFunction(PyUFuncObject *self, PyObject *args, PyObject *kwds,
 			PyArrayObject **mps)
 {
 	PyUFuncLoopObject *loop;
 	int i;
         NPY_BEGIN_THREADS_DEF
 
-	if (!(loop = construct_loop(self, args, mps))) return -1;
+        if (!(loop = construct_loop(self, args, kwds, mps))) return -1;
         if (loop->notimplemented) {ufuncloop_dealloc(loop); return -2;}
 
 	NPY_LOOP_BEGIN_THREADS
@@ -1833,7 +1889,7 @@
 	loop->instrides = (*arr)->strides[axis];
 
 	if (select_types(loop->ufunc, arg_types, &(loop->function),
-			 &(loop->funcdata), scalars) == -1) goto fail;
+			 &(loop->funcdata), scalars, NULL) == -1) goto fail;
 
 	/* output type may change -- if it does
 	 reduction is forced into that type
@@ -1844,7 +1900,7 @@
 		arg_types[0] = otype;
 		arg_types[1] = otype;
 		if (select_types(loop->ufunc, arg_types, &(loop->function),
-				 &(loop->funcdata), scalars) == -1)
+				 &(loop->funcdata), scalars, NULL) == -1)
 			goto fail;
 	}
 
@@ -2769,7 +2825,7 @@
 }
 
 static PyObject *
-ufunc_generic_call(PyUFuncObject *self, PyObject *args)
+ufunc_generic_call(PyUFuncObject *self, PyObject *args, PyObject *kwds)
 {
 	int i;
 	PyTupleObject *ret;
@@ -2783,7 +2839,7 @@
 	   if something goes wrong. */
 	for(i=0; i<self->nargs; i++) mps[i] = NULL;
 
-        errval = PyUFunc_GenericFunction(self, args, mps);
+        errval = PyUFunc_GenericFunction(self, args, kwds, mps);
         if (errval < 0) {
 		for(i=0; i<self->nargs; i++) {
 			PyArray_XDECREF_ERR(mps[i]);
@@ -3317,7 +3373,7 @@
  */
 
 static PyObject *
-ufunc_outer(PyUFuncObject *self, PyObject *args)
+ufunc_outer(PyUFuncObject *self, PyObject *args, PyObject *kwds)
 {
 	int i;
 	PyObject *ret;
@@ -3376,7 +3432,7 @@
 	Py_DECREF(ap1);
 	Py_DECREF(ap2);
 	Py_DECREF(ap_new);
-	ret = ufunc_generic_call(self, new_args);
+	ret = ufunc_generic_call(self, new_args, kwds);
 	Py_DECREF(new_args);
 	return ret;
 
@@ -3385,7 +3441,6 @@
 	Py_XDECREF(ap2);
 	Py_XDECREF(ap_new);
 	return NULL;
-
 }
 
 
@@ -3416,7 +3471,7 @@
 	 METH_VARARGS | METH_KEYWORDS},
 	{"reduceat",  (PyCFunction)ufunc_reduceat,
 	 METH_VARARGS | METH_KEYWORDS},
-	{"outer", (PyCFunction)ufunc_outer, METH_VARARGS},
+	{"outer", (PyCFunction)ufunc_outer, METH_VARARGS | METH_KEYWORDS},
 	{NULL,		NULL}		/* sentinel */
 };
 
@@ -3590,7 +3645,7 @@
 	0,		               /*tp_as_sequence*/
 	0,		               /*tp_as_mapping*/
 	(hashfunc)0,		       /*tp_hash*/
-	(ternaryfunc)ufunc_generic_call,		/*tp_call*/
+	(ternaryfunc)ufunc_generic_call, /*tp_call*/
 	(reprfunc)ufunc_repr,	       /*tp_str*/
         0,	          	       /* tp_getattro */
         0,			       /* tp_setattro */




More information about the Numpy-svn mailing list