[Numpy-discussion] Notes on transitioning to numarray. [Addendum]

Tim Hochberg tim.hochberg at ieee.org
Mon Nov 10 10:11:09 CST 2003


Here's one more thing I just ran into. It's related to over/underflow 
handling, so it's even topical.

I think that the _pushmodes method of NumError (in unfunc.py) should be 
using _gemodestack(0), not
getmodestack(1). That is::

    def _pushmodes(self, modes):
        l = self._getmodestack(0) # XXX changed be TAH
        l.append(modes)

What can happen now is:

   - New thread is started.
   - pushMode is called before any calls to getMode, resulting in a 
modestack one deep.
   - the corresponding popMode is called, resulting in an illegal stack 
that is zero deep.
   - there is an over/underflow and getMode fails because of the zero 
length stack.

While I'm on the subject, I think that the way the default stack entry 
is created should be changed. Currently there is no way to assign a 
default error mode for all threads. The simplest approach would be add a 
setDefaultMode method to Error. Error._defaultmode would be set in 
__init__ to _NumErrorMode(), but could subsequently be re-set with 
setDefaultMode. _defaultmode would be used to initialize the default 
value in _getmodestack. Specifically:

class NumError:

    def __init__(self, all="warn",
            overflow=None, underflow=None, dividebyzero=None, invalid=None):
        self._defaultmode =  _NumErrorMode()
        self._modestack = {}  # map of stacks indexed by thread id
        self.setMode(all=all, underflow=underflow, overflow=overflow,
                     dividebyzero=dividebyzero, invalid=invalid)

    def _getmodestack(self, empty_default=0):
        id = safethread.get_ident()
        try:
            l = self._modestack[id]
        except KeyError:
            if empty_default:
                l = []
            else:
                l = [self._defaultmode ]
            self._modestack[id] = l
        return l

    def setDefaultMode(self, all="warn", overflow=None, underflow=None,
                      dividebyzero=None, invalid=None):
        self._defaultmode = _NumErrorMode(all, overflow, underflow,
                                      dividebyzero, invalid) )

    #....


While I'm at it, what's the point of empty_default? I can't figure out 
when it would be useful.


-tim






More information about the Numpy-discussion mailing list