[Numpy-svn] r3361 - in trunk/numpy/core: . include/numpy src
numpy-svn at scipy.org
numpy-svn at scipy.org
Wed Oct 18 20:13:51 EDT 2006
Author: oliphant
Date: 2006-10-18 19:13:48 -0500 (Wed, 18 Oct 2006)
New Revision: 3361
Modified:
trunk/numpy/core/include/numpy/ndarrayobject.h
trunk/numpy/core/include/numpy/ufuncobject.h
trunk/numpy/core/numeric.py
trunk/numpy/core/src/scalarmathmodule.c.src
trunk/numpy/core/src/ufuncobject.c
trunk/numpy/core/src/umathmodule.c.src
Log:
Add print and log facilities to error handling and change the default error mode to divide='print', over='print', invalid='print', and under='ignore'
Modified: trunk/numpy/core/include/numpy/ndarrayobject.h
===================================================================
--- trunk/numpy/core/include/numpy/ndarrayobject.h 2006-10-18 22:52:29 UTC (rev 3360)
+++ trunk/numpy/core/include/numpy/ndarrayobject.h 2006-10-19 00:13:48 UTC (rev 3361)
@@ -30,7 +30,7 @@
#define NPY_SUCCEED 1
/* Helpful to distinguish what is installed */
-#define NPY_VERSION 0x01000008
+#define NPY_VERSION 0x01000009
/* Some platforms don't define bool, long long, or long double.
Handle that here.
Modified: trunk/numpy/core/include/numpy/ufuncobject.h
===================================================================
--- trunk/numpy/core/include/numpy/ufuncobject.h 2006-10-18 22:52:29 UTC (rev 3360)
+++ trunk/numpy/core/include/numpy/ufuncobject.h 2006-10-19 00:13:48 UTC (rev 3361)
@@ -27,18 +27,20 @@
#define UFUNC_ERR_WARN 1
#define UFUNC_ERR_RAISE 2
#define UFUNC_ERR_CALL 3
+#define UFUNC_ERR_PRINT 4
+#define UFUNC_ERR_LOG 5
/* Python side integer mask */
-#define UFUNC_MASK_DIVIDEBYZERO 0x03
-#define UFUNC_MASK_OVERFLOW 0x0c
-#define UFUNC_MASK_UNDERFLOW 0x30
-#define UFUNC_MASK_INVALID 0xc0
+#define UFUNC_MASK_DIVIDEBYZERO 0x07
+#define UFUNC_MASK_OVERFLOW 0x3f
+#define UFUNC_MASK_UNDERFLOW 0x1ff
+#define UFUNC_MASK_INVALID 0xfff
#define UFUNC_SHIFT_DIVIDEBYZERO 0
-#define UFUNC_SHIFT_OVERFLOW 2
-#define UFUNC_SHIFT_UNDERFLOW 4
-#define UFUNC_SHIFT_INVALID 6
+#define UFUNC_SHIFT_OVERFLOW 3
+#define UFUNC_SHIFT_UNDERFLOW 6
+#define UFUNC_SHIFT_INVALID 9
/* platform-dependent code translates floating point
@@ -49,8 +51,14 @@
#define UFUNC_FPE_UNDERFLOW 4
#define UFUNC_FPE_INVALID 8
-#define UFUNC_ERR_DEFAULT 0 /* Default error mode */
+#define UFUNC_ERR_DEFAULT 0 /* Error mode that avoids look-up (no checking) */
+ /* Default user error mode */
+#define UFUNC_ERR_DEFAULT2 \
+ (UFUNC_ERR_PRINT << UFUNC_SHIFT_DIVIDEBYZERO) + \
+ (UFUNC_ERR_PRINT << UFUNC_SHIFT_OVERFLOW) + \
+ (UFUNC_ERR_PRINT << UFUNC_SHIFT_INVALID)
+
/* Only internal -- not exported, yet*/
typedef struct {
/* Multi-iterator portion --- needs to be present in this order
@@ -70,8 +78,9 @@
/* The error handling */
int errormask; /* Integer showing desired error handling */
PyObject *errobj; /* currently a tuple with
- (string, func or None)
+ (string, func or obj with write method or None)
*/
+ int first;
/* Specific function and data to use */
PyUFuncGenericFunction function;
@@ -134,6 +143,7 @@
/* The error handling */
int errormask;
PyObject *errobj;
+ int first;
PyUFuncGenericFunction function;
void *funcdata;
@@ -201,12 +211,13 @@
#include "__ufunc_api.h"
#define UFUNC_PYVALS_NAME "UFUNC_PYVALS"
-
-#define UFUNC_CHECK_ERROR(arg) \
- if (((arg)->obj && PyErr_Occurred()) || \
- ((arg)->errormask && \
- PyUFunc_checkfperr((arg)->errormask, \
- (arg)->errobj))) \
+
+#define UFUNC_CHECK_ERROR(arg) \
+ if (((arg)->obj && PyErr_Occurred()) || \
+ ((arg)->errormask && \
+ PyUFunc_checkfperr((arg)->errormask, \
+ (arg)->errobj, \
+ &(arg)->first))) \
goto fail
/* This code checks the IEEE status flags in a platform-dependent way */
Modified: trunk/numpy/core/numeric.py
===================================================================
--- trunk/numpy/core/numeric.py 2006-10-18 22:52:29 UTC (rev 3360)
+++ trunk/numpy/core/numeric.py 2006-10-19 00:13:48 UTC (rev 3361)
@@ -633,7 +633,9 @@
_errdict = {"ignore":ERR_IGNORE,
"warn":ERR_WARN,
"raise":ERR_RAISE,
- "call":ERR_CALL}
+ "call":ERR_CALL,
+ "print":ERR_PRINT,
+ "log":ERR_LOG}
_errdict_rev = {}
for key in _errdict.keys():
@@ -690,10 +692,10 @@
Returns a dictionary with entries "divide", "over", "under", and
"invalid", whose values are from the strings
- "ignore", "warn", "raise", and "call".
+ "ignore", "print", "log", "warn", "raise", and "call".
"""
maskvalue = umath.geterrobj()[1]
- mask = 3
+ mask = 7
res = {}
val = (maskvalue >> SHIFT_DIVIDEBYZERO) & mask
res['divide'] = _errdict_rev[val]
@@ -728,7 +730,8 @@
def seterrcall(func):
"""Set the callback function used when a floating-point error handler
- is set to 'call'.
+ is set to 'call' or the object with a write method for use when
+ the floating-point error handler is set to 'log'
'func' should be a function that takes two arguments. The first is
type of error ("divide", "over", "under", or "invalid"), and the second
@@ -737,7 +740,8 @@
Returns the old handler.
"""
if func is not None and not callable(func):
- raise ValueError, "Only callable can be used as callback"
+ if not hasattr(func, 'write') or not callable(func.write):
+ raise ValueError, "Only callable can be used as callback"
pyvals = umath.geterrobj()
old = geterrcall()
pyvals[2] = func
@@ -784,7 +788,7 @@
seterr(**self.oldstate)
def _setdef():
- defval = [UFUNC_BUFSIZE_DEFAULT, ERR_DEFAULT, None]
+ defval = [UFUNC_BUFSIZE_DEFAULT, ERR_DEFAULT2, None]
umath.seterrobj(defval)
# set the default values
Modified: trunk/numpy/core/src/scalarmathmodule.c.src
===================================================================
--- trunk/numpy/core/src/scalarmathmodule.c.src 2006-10-18 22:52:29 UTC (rev 3360)
+++ trunk/numpy/core/src/scalarmathmodule.c.src 2006-10-19 00:13:48 UTC (rev 3361)
@@ -550,6 +550,7 @@
#if @fperr@
int retstatus;
+ int first;
#endif
switch(_ at name@_convert2_to_ctypes(a, &arg1, b, &arg2)) {
@@ -584,7 +585,8 @@
if (PyUFunc_GetPyValues("@name at _scalars", &bufsize, &errmask,
&errobj) < 0)
return NULL;
- if (PyUFunc_handlefperr(errmask, errobj, retstatus))
+ first = 1;
+ if (PyUFunc_handlefperr(errmask, errobj, retstatus, &first))
return NULL;
}
#endif
@@ -625,6 +627,7 @@
PyObject *ret;
@name@ arg1, arg2;
int retstatus;
+ int first;
#if @cmplx@
@name@ out = {0,0};
@@ -678,7 +681,8 @@
if (PyUFunc_GetPyValues("@name at _scalars", &bufsize, &errmask,
&errobj) < 0)
return NULL;
- if (PyUFunc_handlefperr(errmask, errobj, retstatus))
+ first = 1;
+ if (PyUFunc_handlefperr(errmask, errobj, retstatus, &first))
return NULL;
}
Modified: trunk/numpy/core/src/ufuncobject.c
===================================================================
--- trunk/numpy/core/src/ufuncobject.c 2006-10-18 22:52:29 UTC (rev 3360)
+++ trunk/numpy/core/src/ufuncobject.c 2006-10-19 00:13:48 UTC (rev 3361)
@@ -473,7 +473,7 @@
*/
static int
-_error_handler(int method, PyObject *errobj, char *errtype, int retstatus)
+_error_handler(int method, PyObject *errobj, char *errtype, int retstatus, int *first)
{
PyObject *pyfunc, *ret, *args;
char *name=PyString_AS_STRING(PyTuple_GET_ITEM(errobj,0));
@@ -512,6 +512,29 @@
Py_DECREF(ret);
break;
+ case UFUNC_ERR_PRINT:
+ if (*first) {
+ fprintf(stderr, "Warning: %s encountered in %s\n", errtype, name);
+ *first = 0;
+ }
+ break;
+ case UFUNC_ERR_LOG:
+ if (first) {
+ *first = 0;
+ pyfunc = PyTuple_GET_ITEM(errobj, 1);
+ if (pyfunc == Py_None) {
+ PyErr_Format(PyExc_NameError,
+ "log specified for %s (in %s) but no " \
+ "object with write method found.",
+ errtype, name);
+ goto fail;
+ }
+ snprintf(msg, 100, "Warning: %s encountered in %s\n", errtype, name);
+ ret = PyObject_CallMethod(pyfunc, "write", "s", msg);
+ if (ret == NULL) goto fail;
+ Py_DECREF(ret);
+ }
+ break;
}
DISABLE_C_API
return 0;
@@ -535,13 +558,13 @@
handle = errmask & UFUNC_MASK_##NAME;\
if (handle && \
_error_handler(handle >> UFUNC_SHIFT_##NAME, \
- errobj, str, retstatus) < 0) \
+ errobj, str, retstatus, first) < 0) \
return -1; \
}}
/*UFUNC_API*/
static int
-PyUFunc_handlefperr(int errmask, PyObject *errobj, int retstatus)
+PyUFunc_handlefperr(int errmask, PyObject *errobj, int retstatus, int *first)
{
int handle;
if (errmask && retstatus) {
@@ -558,13 +581,13 @@
/*UFUNC_API*/
static int
-PyUFunc_checkfperr(int errmask, PyObject *errobj)
+PyUFunc_checkfperr(int errmask, PyObject *errobj, int *first)
{
int retstatus;
/* 1. check hardware flag --- this is platform dependent code */
retstatus = PyUFunc_getfperr();
- return PyUFunc_handlefperr(errmask, errobj, retstatus);
+ return PyUFunc_handlefperr(errmask, errobj, retstatus, first);
}
@@ -958,14 +981,21 @@
*errmask);
return -1;
}
-
+
retval = PyList_GET_ITEM(ref, 2);
if (retval != Py_None && !PyCallable_Check(retval)) {
- PyErr_SetString(PyExc_TypeError,
- "callback function must be callable");
- return -1;
+ PyObject *temp;
+ temp = PyObject_GetAttrString(retval, "write");
+ if (temp == NULL || !PyCallable_Check(temp)) {
+ PyErr_SetString(PyExc_TypeError,
+ "python object must be callable or have " \
+ "a callable write method");
+ Py_XDECREF(temp);
+ return -1;
+ }
+ Py_DECREF(temp);
}
-
+
*errobj = Py_BuildValue("NO",
PyString_FromString(name),
retval);
@@ -1571,6 +1601,7 @@
}
loop->errobj = NULL;
loop->notimplemented = 0;
+ loop->first = 1;
name = self->name ? self->name : "";
@@ -2057,6 +2088,7 @@
loop->it = NULL;
loop->rit = NULL;
loop->errobj = NULL;
+ loop->first = 1;
loop->decref=NULL;
loop->N = (*arr)->dimensions[axis];
loop->instrides = (*arr)->strides[axis];
Modified: trunk/numpy/core/src/umathmodule.c.src
===================================================================
--- trunk/numpy/core/src/umathmodule.c.src 2006-10-18 22:52:29 UTC (rev 3360)
+++ trunk/numpy/core/src/umathmodule.c.src 2006-10-19 00:13:48 UTC (rev 3361)
@@ -2181,7 +2181,10 @@
ADDCONST(ERR_WARN);
ADDCONST(ERR_CALL);
ADDCONST(ERR_RAISE);
+ ADDCONST(ERR_PRINT);
+ ADDCONST(ERR_LOG);
ADDCONST(ERR_DEFAULT);
+ ADDCONST(ERR_DEFAULT2);
ADDCONST(SHIFT_DIVIDEBYZERO);
ADDCONST(SHIFT_OVERFLOW);
More information about the Numpy-svn
mailing list