[Numpy-discussion] Behavior of array scalars

Sasha ndarray at mac.com
Fri Feb 17 17:56:05 CST 2006


On 2/17/06, Travis Oliphant <oliphant at ee.byu.edu> wrote:
> Sasha wrote:
>
> >Maybe we can change ufunc logic so that when the output argument is
> >supplied it is returned without scalar conversion.
> >
> >
> That seems sensible.

Attached patch implements this idea.  With the patch applied:

>>> from numpy import *
>>> x = array(5)
>>> add(x,5,x)
array(10)
>>> x+=5
>>> x
array(15)

The patch passes all the tests, but I would like to hear from others
before commit.  Personally, I am unhappy that I had to change C-API
function.
-------------- next part --------------
Index: numpy/core/src/ufuncobject.c
===================================================================
--- numpy/core/src/ufuncobject.c	(revision 2128)
+++ numpy/core/src/ufuncobject.c	(working copy)
@@ -846,7 +846,8 @@
 #undef _GETATTR_
 
 static int
-construct_matrices(PyUFuncLoopObject *loop, PyObject *args, PyArrayObject **mps)
+construct_matrices(PyUFuncLoopObject *loop, PyObject *args,
+		   PyArrayObject **mps, Bool *supplied_output)
 {
         int nargs, i, maxsize;
         int arg_types[MAX_ARGS];
@@ -952,6 +953,7 @@
                         mps[i] = NULL;
                         continue;
                 }
+		supplied_output[i] = TRUE;
                 Py_INCREF(mps[i]);
                 if (!PyArray_Check((PyObject *)mps[i])) {
 			PyObject *new;
@@ -1000,6 +1002,7 @@
                                                               NULL, NULL,
                                                               0, 0, NULL);
                         if (mps[i] == NULL) return -1;
+			supplied_output[i] = FALSE;
                 }
 
 		/* reset types for outputs that are equivalent 
@@ -1271,7 +1274,8 @@
 }
 
 static PyUFuncLoopObject *
-construct_loop(PyUFuncObject *self, PyObject *args, PyArrayObject **mps)
+construct_loop(PyUFuncObject *self, PyObject *args, 
+	       PyArrayObject **mps, Bool* supplied_output)
 {
 	PyUFuncLoopObject *loop;
 	int i;
@@ -1299,7 +1303,7 @@
 				&(loop->errobj)) < 0) goto fail;
         
 	/* Setup the matrices */
-	if (construct_matrices(loop, args, mps) < 0) goto fail;
+	if (construct_matrices(loop, args, mps, supplied_output) < 0) goto fail;
 
 	PyUFunc_clearfperr();
 
@@ -1381,13 +1385,13 @@
 /*UFUNC_API*/
 static int 
 PyUFunc_GenericFunction(PyUFuncObject *self, PyObject *args, 
-			PyArrayObject **mps) 
+			PyArrayObject **mps, Bool* supplied_output) 
 {
 	PyUFuncLoopObject *loop;
 	int i;
         BEGIN_THREADS_DEF
 
-	if (!(loop = construct_loop(self, args, mps))) return -1;
+	  if (!(loop = construct_loop(self, args, mps, supplied_output))) return -1;
         if (loop->notimplemented) {ufuncloop_dealloc(loop); return -2;}
 
 	LOOP_BEGIN_THREADS
@@ -2561,6 +2565,7 @@
 	PyTupleObject *ret;
 	PyArrayObject *mps[MAX_ARGS];
 	PyObject *retobj[MAX_ARGS];
+	Bool supplied_output[MAX_ARGS];
 	PyObject *res;
 	PyObject *wrap;
         int errval;
@@ -2569,7 +2574,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, mps, supplied_output);
         if (errval < 0) {
 		for(i=0; i<self->nargs; i++) Py_XDECREF(mps[i]);
 		if (errval == -1)
@@ -2619,7 +2624,9 @@
 				continue;
 			}
 		}
-		retobj[i] = PyArray_Return(mps[j]);
+		retobj[i] = supplied_output[j]
+		  ? (PyObject *)mps[j]
+		  : PyArray_Return(mps[j]);
 	}
 	
 	if (self->nout == 1) { 


More information about the Numpy-discussion mailing list