diff options
-rw-r--r-- | scipy/base/include/scipy/ufuncobject.h | 4 | ||||
-rw-r--r-- | scipy/base/numeric.py | 114 | ||||
-rw-r--r-- | scipy/base/src/ufuncobject.c | 169 | ||||
-rw-r--r-- | scipy/base/src/umathmodule.c.src | 4 |
4 files changed, 136 insertions, 155 deletions
diff --git a/scipy/base/include/scipy/ufuncobject.h b/scipy/base/include/scipy/ufuncobject.h index d5dcbb861..5364595b5 100644 --- a/scipy/base/include/scipy/ufuncobject.h +++ b/scipy/base/include/scipy/ufuncobject.h @@ -179,9 +179,7 @@ typedef struct { #include "__ufunc_api.h" -#define UFUNC_ERRMASK_NAME "_UFUNC_ERRMASK" -#define UFUNC_ERRFUNC_NAME "_UFUNC_ERRFUNC" -#define UFUNC_BUFSIZE_NAME "_UFUNC_BUFSIZE" +#define UFUNC_PYVALS_NAME "UFUNC_PYVALS" #define UFUNC_CHECK_ERROR() \ if ((loop->obj && PyErr_Occurred()) || \ diff --git a/scipy/base/numeric.py b/scipy/base/numeric.py index 0d8c3f4cf..2e0ac1d35 100644 --- a/scipy/base/numeric.py +++ b/scipy/base/numeric.py @@ -275,6 +275,38 @@ def allclose (a, b, rtol=1.e-5, atol=1.e-8): return alltrue(ravel(d)) +def _setpyvals(lst, frame, where=0): + if not isinstance(lst, list) or len(lst) != 3: + raise ValueError, "Invalid pyvalues (length 3 list needed)." + + try: + wh = where.lower()[0] + except (AttributeError, TypeError, IndexError): + wh = None + + if where==0 or wh == 'l': + frame.f_locals[UFUNC_PYVALS_NAME] = lst + elif where == 1 or wh == 'g': + frame.f_globals[UFUNC_PYVALS_NAME] = lst + elif where == 2 or wh == 'b': + frame.f_builtins[UFUNC_PYVALS_NAME] = lst + + return + +def _getpyvals(frame): + try: + return frame.f_locals[UFUNC_PYVALS_NAME] + except KeyError: + try: + return frame.f_globals[UFUNC_PYVALS_NAME] + except KeyError: + try: + return frame.f_builtins[UFUNC_PYVALS_NAME] + except KeyError: + return [UFUNC_BUFSIZE_DEFAULT, ERR_DEFAULT, None] + + + _errdict = {"ignore":ERR_IGNORE, "warn":ERR_WARN, "raise":ERR_RAISE, @@ -290,31 +322,16 @@ def seterr(divide="ignore", over="ignore", under="ignore", invalid="ignore", whe (_errdict[over] << SHIFT_OVERFLOW ) + \ (_errdict[under] << SHIFT_UNDERFLOW) + \ (_errdict[invalid] << SHIFT_INVALID) - frame = sys._getframe().f_back - try: - wh = where.lower()[0] - except (AttributeError, TypeError, IndexError): - wh = None - if where==0 or wh == 'l': - frame.f_locals[UFUNC_ERRMASK_NAME] = maskvalue - elif where == 1 or wh == 'g': - frame.f_globals[UFUNC_ERRMASK_NAME] = maskvalue - elif where == 2 or wh == 'b': - frame.f_builtins[UFUNC_ERRMASK_NAME] = maskvalue - return - frame.f_locals[UFUNC_ERRMASK_NAME] = maskvalue - return - -seterr() - -def geterr(): frame = sys._getframe().f_back - try: - maskvalue = frame.f_locals[UFUNC_ERRMASK_NAME] - except KeyError: - maskvalue = ERR_DEFAULT - + pyvals = _getpyvals(frame) + pyvals[1] = maskvalue + _setpyvals(pyvals, frame, where) + +def geterr(): + frame = sys._getframe().f_back + maskvalue = _getpyvals(frame)[1] + mask = 3 res = {} val = (maskvalue >> SHIFT_DIVIDEBYZERO) & mask @@ -330,39 +347,36 @@ def geterr(): def setbufsize(size, where=0): if size > 10e6: raise ValueError, "Very big buffers.. %s" % size - frame = sys._getframe().f_back - try: - wh = where.lower()[0] - except (AttributeError, TypeError, IndexError): - wh = None - if where == 0 or wh == 'l': - frame.f_locals[UFUNC_BUFSIZE_NAME] = size - elif where == 1 or wh == 'g': - frame.f_globals[UFUNC_BUFSIZE_NAME] = size - elif where == 2 or wh == 'b': - frame.f_builtins[UFUNC_BUFSIZE_NAME] = size - return -setbufsize(10000, 1) + frame = sys._getframe().f_back + pyvals = _getpyvals(frame) + pyvals[0] = size + _setpyvals(pyvals, frame, where) -def getbufsize(size): +def getbufsize(): frame = sys._getframe().f_back - try: - retval = frame.f_locals[UFUNC_BUFSIZE_NAME] - except KeyError: - retval = frame.f_globals[UFUNC_BUFSIZE_NAME] - except KeyError: - retval = frame.f_builtins[UFUNC_BUFSIZE_NAME] - except KeyError: - retvalue = UFUNC_BUFSIZE_DEFAULT + return _getpyvals(frame)[0] - return retval +def seterrcall(func, where=0): + if not callable(func): + raise ValueError, "Only callable can be used as callback" + frame = sys._getframe().f_back + pyvals = _getpyvals(frame) + pyvals[2] = func + _setpyvals(pyvals, frame, where) +def geterrcall(): + frame = sys._getframe().f_back + return _getpyvals(frame)[2] -# Set the UFUNC_BUFSIZE_NAME to something -# Set the UFUNC_ERRMASK_NAME to something -seterr(where='builtin') -setbufsize(UFUNC_BUFSIZE_DEFAULT,where='builtin') +def _setdef(): + frame = sys._getframe() + defval = [UFUNC_BUFSIZE_DEFAULT, ERR_DEFAULT, None] + frame.f_globals[UFUNC_PYVALS_NAME] = defval + frame.f_builtins[UFUNC_PYVALS_NAME] = defval + +# set the default values +_setdef() Inf = inf = infty = Infinity = PINF nan = NaN = NAN diff --git a/scipy/base/src/ufuncobject.c b/scipy/base/src/ufuncobject.c index ccec5e230..a8f3e2d92 100644 --- a/scipy/base/src/ufuncobject.c +++ b/scipy/base/src/ufuncobject.c @@ -670,57 +670,72 @@ select_types(PyUFuncObject *self, int *arg_types, return 0; } - - static int -_getintfromvar(char *str, int deflt) +_getpyvalues(char *name, int *bufsize, int *errmask, PyObject **errobj) { - PyObject *thedict; - PyObject *ref; - int retval=deflt; - - thedict = PyEval_GetLocals(); - ref = PyDict_GetItemString(thedict, str); - if (ref == NULL) { - thedict = PyEval_GetGlobals(); - ref = PyDict_GetItemString(thedict, str); - } - if (ref == NULL) { - thedict = PyEval_GetBuiltins(); - ref = PyDict_GetItemString(thedict, str); - } - if (ref != NULL) retval = (int) PyInt_AsLong(ref); - if (ref == NULL || retval == -1) retval = deflt; - PyErr_Clear(); - return retval; -} -static PyObject * -_getfuncfromvar(char *str, PyObject *deflt) -{ PyObject *thedict; - PyObject *ref; + PyObject *ref=NULL; PyObject *retval; thedict = PyEval_GetLocals(); - ref = PyDict_GetItemString(thedict, str); + ref = PyDict_GetItemString(thedict, UFUNC_PYVALS_NAME); if (ref == NULL) { thedict = PyEval_GetGlobals(); - ref = PyDict_GetItemString(thedict, str); + ref = PyDict_GetItemString(thedict, UFUNC_PYVALS_NAME); } if (ref == NULL) { - thedict = PyEval_GetBuiltins(); - ref = PyDict_GetItemString(thedict, str); + thedict = PyEval_GetBuiltins(); + ref = PyDict_GetItemString(thedict, UFUNC_PYVALS_NAME); + } + if (ref == NULL) { + *errmask = UFUNC_ERR_DEFAULT; + *errobj = Py_BuildValue("NO", + PyString_FromString(name), + Py_None); + *bufsize = PyArray_BUFSIZE; + return 0; } - if (ref != NULL) retval = ref; - else retval = deflt; + if (!PyList_Check(ref) || (PyList_GET_SIZE(ref)!=3)) { + PyErr_Format(PyExc_TypeError, "%s must be a length 3 list.", + UFUNC_PYVALS_NAME); + return -1; + } + + *bufsize = PyInt_AsLong(PyList_GET_ITEM(ref, 0)); + if ((*bufsize == -1) && PyErr_Occurred()) return -1; + if ((*bufsize < PyArray_MIN_BUFSIZE) || \ + (*bufsize > PyArray_MAX_BUFSIZE)) { + PyErr_Format(PyExc_ValueError, + "The buffer size (%d) is not " \ + "in range (%d - %d)", + *bufsize, PyArray_MIN_BUFSIZE, + PyArray_MAX_BUFSIZE); + return -1; + } + + *errmask = PyInt_AsLong(PyList_GET_ITEM(ref, 1)); + if (*errmask < 0) { + if (PyErr_Occurred()) return -1; + PyErr_Format(PyExc_ValueError, \ + "Invalid error mask (%d)", + *errmask); + return -1; + } + + retval = PyList_GET_ITEM(ref, 2); if (retval != Py_None && !PyCallable_Check(retval)) { - PyErr_Format(PyExc_ValueError, - "%s if provided must be callable", str); - return NULL; + PyErr_SetString(PyExc_ValueError, + "callback function must be callable"); + return -1; } - Py_INCREF(retval); - return retval; + + *errobj = Py_BuildValue("NO", + PyString_FromString(name), + retval); + if (*errobj == NULL) return -1; + + return 0; } @@ -849,17 +864,6 @@ construct_matrices(PyUFuncLoopObject *loop, PyObject *args, PyArrayObject **mps) if (select_types(loop->ufunc, arg_types, &(loop->function), &(loop->funcdata), scalars) == -1) return -1; - - /* This is the buffer size in number of elements.*/ - loop->bufsize = _getintfromvar(UFUNC_BUFSIZE_NAME, PyArray_BUFSIZE); - if ((loop->bufsize < PyArray_MIN_BUFSIZE) || \ - (loop->bufsize > PyArray_MAX_BUFSIZE)) { - PyErr_Format(PyExc_ValueError, "The buffer size (%d) is not " \ - "in range (%d - %d)", - loop->bufsize, PyArray_MIN_BUFSIZE, - PyArray_MAX_BUFSIZE); - return -1; - } /* Create copies for some of the arrays if appropriate */ if (_create_copies(loop, arg_types, mps) < 0) return -1; @@ -1145,10 +1149,12 @@ construct_loop(PyUFuncObject *self, PyObject *args, PyArrayObject **mps) PyErr_SetString(PyExc_ValueError, "function not supported"); return NULL; } - if ((loop=PyObject_NEW(PyUFuncLoopObject, &PyUFuncLoop_Type)) == NULL) return NULL; - + /* --- no real speed increase this way + loop = malloc(sizeof(PyUFuncLoopObject)); + */ + loop->index = 0; loop->ufunc = self; Py_INCREF(self); @@ -1159,25 +1165,14 @@ construct_loop(PyUFuncObject *self, PyObject *args, PyArrayObject **mps) } loop->errobj = NULL; + if (_getpyvalues((self->name ? self->name : ""), + &(loop->bufsize), &(loop->errormask), + &(loop->errobj)) < 0) + goto fail; + /* Setup the matrices */ if (construct_matrices(loop, args, mps) < 0) goto fail; - loop->errormask = _getintfromvar(UFUNC_ERRMASK_NAME, - UFUNC_ERR_DEFAULT); - if (loop->errormask < 0) { - PyErr_Format(PyExc_ValueError, - "Invalid error mask (%d)", - loop->errormask); - goto fail; - } - - loop->errobj = Py_BuildValue("NN", - PyString_FromString((self->name ? \ - self->name : "")), - _getfuncfromvar(UFUNC_ERRFUNC_NAME, - Py_None)); - if (loop->errobj == NULL) goto fail; - PyUFunc_clearfperr(); return loop; @@ -1416,14 +1411,14 @@ PyUFunc_GenericFunction(PyUFuncObject *self, PyObject *args, } LOOP_END_THREADS - - Py_DECREF(loop); + + Py_DECREF(loop); return 0; fail: LOOP_END_THREADS - - Py_XDECREF(loop); + + Py_DECREF(loop); return -1; } @@ -1530,19 +1525,10 @@ construct_reduce(PyUFuncObject *self, PyArrayObject **arr, int axis, &(loop->funcdata), scalars) == -1) goto fail; } - - /* Make bufsize depend on a local then module-level variable */ - loop->bufsize = _getintfromvar("UFUNC_BUFSIZE", - PyArray_BUFSIZE); - if ((loop->bufsize < PyArray_MIN_BUFSIZE) || \ - (loop->bufsize > PyArray_MAX_BUFSIZE)) { - PyErr_Format(PyExc_ValueError, - "The buffer size (%d) is not " \ - "in range (%d - %d)", - loop->bufsize, PyArray_MIN_BUFSIZE, - PyArray_MAX_BUFSIZE); - goto fail; - } + + /* get looping parameters from Python */ + if (_getpyvalues(str, &(loop->bufsize), &(loop->errormask), + &(loop->errobj)) < 0) goto fail; /* Make copy if misbehaved or not otype for small arrays */ if (_create_reduce_copy(loop, arr, otype) < 0) goto fail; @@ -1688,22 +1674,6 @@ construct_reduce(PyUFuncObject *self, PyArrayObject **arr, int axis, loop->bufptr[0] = loop->buffer; } } - - loop->errormask = _getintfromvar(UFUNC_ERRMASK_NAME, - UFUNC_ERR_DEFAULT); - if (loop->errormask < 0) { - PyErr_Format(PyExc_ValueError, \ - "Invalid error mask (%d)", - loop->errormask); - goto fail; - - } - - loop->errobj = Py_BuildValue("NN", - PyString_FromString(str), - _getfuncfromvar(UFUNC_ERRFUNC_NAME, - Py_None)); - if (loop->errobj == NULL) goto fail; /* Determine if object arrays are involved */ if (otype == PyArray_OBJECT || aar->descr->type_num == PyArray_OBJECT) @@ -2894,6 +2864,7 @@ static PyTypeObject PyUFuncLoop_Type = { (destructor)ufuncloop_dealloc /*tp_dealloc*/ }; + static PyTypeObject PyUFuncReduce_Type = { PyObject_HEAD_INIT(0) 0, /*ob_size*/ diff --git a/scipy/base/src/umathmodule.c.src b/scipy/base/src/umathmodule.c.src index 700d918ea..46397339d 100644 --- a/scipy/base/src/umathmodule.c.src +++ b/scipy/base/src/umathmodule.c.src @@ -1714,9 +1714,7 @@ DL_EXPORT(void) initumath(void) { ADDCONST(FPE_UNDERFLOW); ADDCONST(FPE_INVALID); - ADDSCONST(ERRMASK_NAME); - ADDSCONST(ERRFUNC_NAME); - ADDSCONST(BUFSIZE_NAME); + ADDSCONST(PYVALS_NAME); #undef ADDCONST #undef ADDSCONST |