summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scipy/base/include/scipy/ufuncobject.h4
-rw-r--r--scipy/base/numeric.py114
-rw-r--r--scipy/base/src/ufuncobject.c169
-rw-r--r--scipy/base/src/umathmodule.c.src4
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