[Numpy-discussion] Scalar-ndarray arguments passed to not_equal

Friedrich Romstedt friedrichromstedt@gmail....
Wed Feb 10 12:57:11 CST 2010


I wonder why there is no response on my e-mail dating back to Feb 4.
Is there nobody interested in it, is somebody working on it, or did it
simply did not come through?  I changed the recipient now to
"Discussion of Numerical Python", hth ...

Sorry when there is double posting now, it's not intended if so.

2010/2/4 Friedrich Romstedt <friedrichromstedt@gmail.com>:
> Hi,
>
> I'm just coding a package for uncertain arrays using the accelerated
> numpy functionality intensively.  I'm sorry, but I have to give some
> background information first.  The package provides a class
> upy.undarray, which holds the nominal value and the uncertainty
> information.  It has methods __add__(other), __radd__(other), ...,
> __eq__(other), __ne__(other), which accept both upy.undarrays and all
> other values suitable for coercion, thus also native numpy.ndarrays.
> But because numpy treats in the statement:
>
> result = numpyarray * upyarray
>
> upyarray as a scalar, because it's not an numpy.ndarray, I have to
> overload the numpy arithmetics by own objects by using
> numpy.set_numeric_ops(add = ..., ..., equal = equal, not_equal =
> not_equal).  The arguments are defined by the module (it will be
> clearifiied below).
>
> Because numpy.add etc. are ufuncs exhibiting attributes, I wrote a
> class to wrap them:
>
> class ufuncWrap:
>        """Wraps numpy ufuncs.  Behaves like the original, with the exception
>        that __call__() will be overloaded."""
>
>        def __init__(self, ufunc, overload):
>                """UFUNC is the ufunc to be wrapped.  OVERLOAD is the name (string)
>                of the undarray method to be used in overloading __call__()."""
>
>                self.ufunc = ufunc
>                self.overload = overload
>
>        def __call__(self, a, b, *args, **kwargs):
>                """When B is an undarray, call B.overload(a), else .ufunc(a, b)."""
>
>                if isinstance(b, undarray):
>                        return getattr(b, self.overload)(a)
>                else:
>                        return self.ufunc(a, b, *args, **kwargs)
>
>        def __getattr__(self, attr):
>                """Return getattr(.ufunc, ATTR)."""
>
>                return getattr(self.ufunc, attr)
>
> I only have to wrap binary operators.
>
> Then, e.g.:
>
> class Equal(ufuncWrap):
>        def __init__(self):
>                ufuncWrap.__init__(self, numpy.equal, '__eq__')
>
> equal = Equal()
>
> This works as expected.
>
> But this approach fails (in first iteration) for a similar class
> NotEqual. I have let the module output the arguments passed to
> ufuncWrap.__call__(), and I found that the statement:
>
> result = (numpyarray != upyarray)
>
> with:
>
> numpyarray = numpy.asarray([1.0])
> upyarray = upy.ndarray([2.0], error = [0.1])
>
> is passed on to NotEqual.__call__() as the arguments:
>
> a = a numpy-array array([1.0])
> b = a numpy-array array(shape = (), dtype = numpy.object), which is a
> scalar array holding the upy.ndarray instance passed to !=.
>
> I can work around the exhbited behaviour by:
>
> class NotEqual(ufuncWrap):
>        def __init__(self):
>                ufuncWrap.__init__(self, numpy.not_equal, '__ne__')
>
>        def __call__(self, a, b, *args, **kwargs):
>                # numpy's calling mechanism of not_equal() seems to have a bug,
>                # such that b is always a numpy.ndarray.  When b should be an undarray,
>                # it is a numpy.ndarray(dtype = numpy.object, shape = ()) ...
>
>                # Make the call also compatible with future, bug-fixed versions.
>                if isinstance(b, numpy.ndarray):
>                        if b.ndim == 0:
>                                # Implement some conversion from scalar array to stored object.
>                                b = b.sum()
>
>                return ufuncWrap.__call__(self, a, b, *args, **kwargs)
>
> What is the reason for the behaviour observed?
>
> I'm using numpy 1.4.0 with Python 2.5.
>
> Friedrich
>


More information about the NumPy-Discussion mailing list