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

numpy-svn at scipy.org numpy-svn at scipy.org
Thu Aug 24 03:36:56 CDT 2006


Author: oliphant
Date: 2006-08-24 03:36:48 -0500 (Thu, 24 Aug 2006)
New Revision: 3056

Modified:
   trunk/numpy/core/code_generators/generate_array_api.py
   trunk/numpy/core/fromnumeric.py
   trunk/numpy/core/include/numpy/ndarrayobject.h
   trunk/numpy/core/include/numpy/npy_interrupt.h
   trunk/numpy/core/ma.py
   trunk/numpy/core/numeric.py
   trunk/numpy/core/src/arraymethods.c
   trunk/numpy/core/src/multiarraymodule.c
Log:
Add rudimentary interrupt handliNG.  Add max, min, round, abs to the numpy space.

Modified: trunk/numpy/core/code_generators/generate_array_api.py
===================================================================
--- trunk/numpy/core/code_generators/generate_array_api.py	2006-08-23 23:39:42 UTC (rev 3055)
+++ trunk/numpy/core/code_generators/generate_array_api.py	2006-08-24 08:36:48 UTC (rev 3056)
@@ -20,6 +20,7 @@
 	npy_bool obval;
 } PyBoolScalarObject;
 
+
 static unsigned int PyArray_GetNDArrayCVersion (void);
 static PyTypeObject PyBigArray_Type;
 static PyTypeObject PyArray_Type;

Modified: trunk/numpy/core/fromnumeric.py
===================================================================
--- trunk/numpy/core/fromnumeric.py	2006-08-23 23:39:42 UTC (rev 3055)
+++ trunk/numpy/core/fromnumeric.py	2006-08-24 08:36:48 UTC (rev 3056)
@@ -379,6 +379,8 @@
         return _wrapit(a, 'max', axis, out)
     return amax(axis, out)
 
+max = amax
+
 def amin(a, axis=None, out=None):
     """Return the minimum of a along dimension axis.
     """
@@ -388,6 +390,8 @@
         return _wrapit(a, 'min', axis, out)
     return amin(axis, out)
 
+min = amin
+
 def alen(a):
     """Return the length of a Python object interpreted as an array
     of at least 1 dimension.
@@ -458,6 +462,8 @@
 
 around = round_
 
+round = round_
+
 def mean(a, axis=None, dtype=None, out=None):
     """mean(a, axis=None, dtype=None)
     Return the arithmetic mean.

Modified: trunk/numpy/core/include/numpy/ndarrayobject.h
===================================================================
--- trunk/numpy/core/include/numpy/ndarrayobject.h	2006-08-23 23:39:42 UTC (rev 3055)
+++ trunk/numpy/core/include/numpy/ndarrayobject.h	2006-08-24 08:36:48 UTC (rev 3056)
@@ -1384,6 +1384,7 @@
                                 does not have ARR_HAS_DESCR flag set) */
 } PyArrayInterface;
 
+
 /* Includes the "function" C-API -- these are all stored in a
    list of pointers --- one for each file
    The two lists are concatenated into one in multiarray.

Modified: trunk/numpy/core/include/numpy/npy_interrupt.h
===================================================================
--- trunk/numpy/core/include/numpy/npy_interrupt.h	2006-08-23 23:39:42 UTC (rev 3055)
+++ trunk/numpy/core/include/numpy/npy_interrupt.h	2006-08-24 08:36:48 UTC (rev 3056)
@@ -10,8 +10,8 @@
 ****Warning***************
 
 Do not allow code that creates temporary memory or increases reference
-counts of Python objects to be interrupted unless you handle decrementing
-the reference counts and freeing any allocated memory in the clean-up code.
+counts of Python objects to be interrupted unless you handle it 
+differently.
 
 **************************
 
@@ -21,7 +21,7 @@
      and store the old one.  
   - run the code to be interrupted -- if an interrupt occurs
      the handler should basically just cause a return to the
-     calling function for clean-up work. 
+     calling function for finish work. 
   - restore the old signal handler 
 
 Of course, every code that allows interrupts must account for
@@ -32,74 +32,90 @@
  1) platform portability (i.e. Microsoft says not to use longjmp
      to return from signal handling.  They have a __try  and __except 
      extension to C instead but what about mingw?).
- 2) how to handle threads
-     a) apparently whether signals are delivered to every thread of
-        the process or the "invoking" thread is platform dependent. 
-     b) if we use global variables to save state, then how is this
-        to be done in a thread-safe way.
- 3) A general-purpose facility must allow for the possibility of
-    re-entrance (i.e. during execution of the code that is allowed
-    to interrupt, we might call back into this very section of code
-    serially). 
 
+ 2) how to handle threads: apparently whether signals are delivered to
+    every thread of the process or the "invoking" thread is platform
+    dependent. --- we don't handle threads for now. 
+ 
+ 3) do we need to worry about re-entrance.  For now, assume the
+    code will not call-back into itself. 
+
 Ideas:
 
  1) Start by implementing an approach that works on platforms that
     can use setjmp and longjmp functionality and does nothing 
-    on other platforms.  Initially only catch SIGINT.
+    on other platforms.  
 
- 2) Handle threads by storing global information in a linked-list
-    with a process-id key.  Then use a call-back function that longjmps
-    only to the correct buffer.
+ 2) Ignore threads --- i.e. do not mix interrupt handling and threads
 
- 3) Store a local copy of the global information and restore it on clean-up
-    so that re-entrance works. 
+ 3) Add a default signal_handler function to the C-API but have the rest
+    use macros. 
 
 
-Interface:
+Simple Interface:
 
-In your C-extension.  around a block of code you want to be interruptable 
 
-NPY_SIG_TRY {
+In your C-extension: around a block of code you want to be interruptable 
+with a SIGINT 
+
+NPY_SIGINT_ON
 [code]
-}
-NPY_SIG_EXCEPT(sigval) {  
-[signal return]
-}
-NPY_SIG_ELSE 
-[normal return]
+NPY_SIGINT_OFF
 
-sigval is a local variable that will receive what
-signal was received.  You can use it to perform different
-actions based on the signal received. 
+In order for this to work correctly, the 
+[code] block must not allocate any memory or alter the reference count of any
+Python objects.  In other words [code] must be interruptible so that continuation
+after NPY_SIGINT_OFF will only be "missing some computations"
 
-Default actions (setting of specific Python errors)
-can be obtained with
+Interrupt handling does not work well with threads. 
 
-NPY_SIG_TRY {
-[code]
-NPY_SIG_EXCEPT_GOTO(label)
-[normal return]
-
-label:
-  [error return]
 */
 
 /* Add signal handling macros */
 
 #ifndef NPY_INTERRUPT_H
 #define NPY_INTERRUPT_H
+           
+#ifndef NPY_NO_SIGNAL
 
-#ifdef NPY_NO_SIGNAL
+#ifndef sigsetjmp
 
-#define NPY_SIG_ON
-#define NPY_SIG_OFF
+#define SIGSETJMP(arg1, arg2) setjmp(arg1)
+#define SIGLONGJMP(arg1, arg2) longjmp(arg1, arg2)
+#define SIGJMP_BUF jmp_buf
 
 #else
 
-#define NPY_SIG_ON
-#define NPY_SIG_OFF
+#define SIGSETJMP(arg1, arg2) sigsetjmp(arg1, arg2)
+#define SIGLONGJMP(arg1, arg2) siglongjmp(arg1, arg2)
+#define SIGJMP_BUF sigjmp_buf
 
-#endif /* NPY_NO_SIGNAL */
+#endif
 
+SIGJMP_BUF _NPY_SIGINT_BUF;
+
+static void
+_npy_sighandler(int signum)
+{
+        PyOS_setsig(signum, SIG_IGN);
+        SIGLONGJMP(_NPY_SIGINT_BUF, signum);
+}
+
+           
+#    define NPY_SIGINT_ON {                                             \
+                PyOS_sighandler_t _npy_sig_save;                        \
+                _npy_sig_save = PyOS_setsig(SIGINT, _npy_sighandler);   \
+                if (SIGSETJMP(_NPY_SIGINT_BUF, 1) == 0) {               \
+                        
+#    define NPY_SIGINT_OFF }                                      \
+        PyOS_setsig(SIGINT, _npy_sig_save);                       \
+        }
+
+#else /* NPY_NO_SIGNAL  */
+
+#  define NPY_SIGINT_ON
+#  define NPY_SIGINT_OFF
+
+#endif /* HAVE_SIGSETJMP */
+
 #endif /* NPY_INTERRUPT_H */

Modified: trunk/numpy/core/ma.py
===================================================================
--- trunk/numpy/core/ma.py	2006-08-23 23:39:42 UTC (rev 3055)
+++ trunk/numpy/core/ma.py	2006-08-24 08:36:48 UTC (rev 3056)
@@ -2144,7 +2144,6 @@
     return MethodType(f, None, array)
 def not_implemented(*args, **kwds):
     raise NotImplementedError, "not yet implemented for numpy.ma arrays"
-array.abs = array.__abs__
 array.all = _m(alltrue)
 array.any = _m(sometrue)
 array.argmax = _m(argmax)

Modified: trunk/numpy/core/numeric.py
===================================================================
--- trunk/numpy/core/numeric.py	2006-08-23 23:39:42 UTC (rev 3055)
+++ trunk/numpy/core/numeric.py	2006-08-24 08:36:48 UTC (rev 3056)
@@ -95,6 +95,8 @@
 extend_all(umath)
 extend_all(numerictypes)
 
+abs = absolute
+
 newaxis = None
 
 ndarray = multiarray.ndarray

Modified: trunk/numpy/core/src/arraymethods.c
===================================================================
--- trunk/numpy/core/src/arraymethods.c	2006-08-23 23:39:42 UTC (rev 3055)
+++ trunk/numpy/core/src/arraymethods.c	2006-08-24 08:36:48 UTC (rev 3056)
@@ -252,8 +252,6 @@
 	return PyArray_Min(self, axis, out);
 }
 
-static char doc_abs[] = "a.abs() returns abs(a)";
-
 static char doc_swapaxes[] = "a.swapaxes(axis1, axis2)  returns new view with axes swapped.";
 
 static PyObject *
@@ -1808,8 +1806,6 @@
 	 METH_VARARGS|METH_KEYWORDS, doc_min},
 	{"ptp", (PyCFunction)array_ptp,
 	 METH_VARARGS|METH_KEYWORDS, doc_ptp},
-        {"abs", (PyCFunction)array_absolute,
-         METH_VARARGS, doc_abs},
 	{"mean", (PyCFunction)array_mean,
 	 METH_VARARGS|METH_KEYWORDS, doc_mean},
 	{"trace", (PyCFunction)array_trace,

Modified: trunk/numpy/core/src/multiarraymodule.c
===================================================================
--- trunk/numpy/core/src/multiarraymodule.c	2006-08-23 23:39:42 UTC (rev 3055)
+++ trunk/numpy/core/src/multiarraymodule.c	2006-08-24 08:36:48 UTC (rev 3056)
@@ -21,7 +21,8 @@
 */
 
 #define _MULTIARRAYMODULE
-#include "numpy/noprefix.h"
+#define NPY_NO_PREFIX
+#include "numpy/arrayobject.h"
 
 #define PyAO PyArrayObject
 
@@ -931,6 +932,10 @@
 	return ret;
 }
 
+/* Why doesn't this just call the ufunc?
+   All we need to do is add it to the list of needed ufuncs.
+ */
+
 /*MULTIARRAY_API
  Conjugate
 */
@@ -6427,6 +6432,24 @@
 
 
 
+#ifndef NPY_NO_SIGNAL
+
+static PyObject *
+test_interrupt(PyObject *self)
+{
+        int a = 0;
+        NPY_SIGINT_ON
+
+        while(1) {
+            a += 1;
+        }
+
+        NPY_SIGINT_OFF
+            
+        return PyInt_FromLong(a);
+}
+#endif
+
 static struct PyMethodDef array_module_methods[] = {
 	{"_get_ndarray_c_version", (PyCFunction)array__get_ndarray_c_version,
 	 METH_VARARGS|METH_KEYWORDS, NULL},
@@ -6481,6 +6504,10 @@
          METH_VARARGS | METH_KEYWORDS, NULL},
         {"compare_chararrays", (PyCFunction)compare_chararrays,
          METH_VARARGS | METH_KEYWORDS, NULL},
+#ifndef NPY_NO_SIGNAL
+        {"test_interrupt", (PyCFunction)test_interrupt,
+         METH_NOARGS, NULL},
+#endif
 	{NULL,		NULL, 0}		/* sentinel */
 };
 
@@ -6680,7 +6707,6 @@
 		return;
 
 	c_api = PyCObject_FromVoidPtr((void *)PyArray_API, NULL);
-	if (PyErr_Occurred()) goto err;
 	PyDict_SetItemString(d, "_ARRAY_API", c_api);
 	Py_DECREF(c_api);
 	if (PyErr_Occurred()) goto err;



More information about the Numpy-svn mailing list