Skip to content

BUG: ndarray.__eq__ does not respect overrides for void #9153

Closed

Description

@mhvk

As noted in #9147, ndarray.__eq__ special-cases void arrays, which means that array-likes cannot use __array_ufunc__ or __array_priority__ to override it:

class B(object):
    def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
        return 'B!'
    def __eq__(self, other):
        return 'B==B'

b = B()
x = np.array([(0, 1, 0)] * 10, dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')])
b == x
# 'B==B'
x == b
# FutureWarning: elementwise == comparison failed and returning scalar instead;...
# False

Likely, all that is needed is to move the RICHCMP_GIVE_UP_IF_NEEDED line up to before the check on void types (see https://github.com/numpy/numpy/blob/master/numpy/core/src/multiarray/arrayobject.c#L1395)

EDIT: the above also means array-like's cannot override via __array_priority__ either.

EDIT 2: For subclasses, the situation is better. If they override __eq__, that will just get called by python. If they do not, things still work more or less, since the code gets elements from the arrays, and compares those using np.equal and combines the results using np.logical_and, both of which do get overridden with __array_ufunc__.

EDIT 3: Crossed out text above reflects #9167, which moves RICHCMP_GIVE_UP_IF_NEEDED and thus solves __array_priority__ and __array_ufunc__ = None, but not a properly defined __array_ufunc__ like the example above.

Activity

  1. changed the title [-]BUG: ndarray.__eq__ does not respect __aray_ufunc__ for void[/-] [+]BUG: ndarray.__eq__ does not respect overrides for void[/+] on May 21, 2017
  2. mhvk commented on May 21, 2017

    @mhvk
    ContributorAuthor

    Note: Since np.equal cannot deal with void, the expectation in this case is not, I think, that __array_ufunc__ is called, since any array-like cannot count on being able to call np.equal. But at least ndarray.__eq__ should return NotImplemented in this case (or the case where B.__array_priority__ is high), to give B.__eq__ a chance.

  3. added this to the 1.13.0 release milestone on May 21, 2017
  4. charris commented on May 21, 2017

    @charris
    Member

    Likely, all that is needed is to move the RICHCMP_GIVE_UP_IF_NEEDED up to before the check on void types

    That looks correct to me.

  5. charris commented on May 21, 2017

    @charris
    Member

    @njsmith Comment?

  6. charris commented on May 23, 2017

    @charris
    Member

    @mhvk Want to make the PR or should I do it?

  7. mhvk commented on May 23, 2017

    @mhvk
    ContributorAuthor

    Was about to make a PR, but then I realized my logic won't quite work: currently, the way binop_should_defer is written is that if __array_ufunc__ is present, the operation is not deferred, because the idea is that np.equal will be called anyway, which will transfer to __array_ufunc__. But of course in the case at hand, np.equal does not get called.

    I'm not quite sure how to fix this...

  8. eric-wieser commented on May 23, 2017

    @eric-wieser
    Member

    Is there a reason that the special handling of == is currently in array_richcompare, and not in ufunc.__call__? It'd still be a hack, but we might as well put it in a place that catches everything, right?

  9. mhvk commented on May 23, 2017

    @mhvk
    ContributorAuthor

    To have it in the ufunc, wouldn't __call__ have to check for void for all ufuncs even though it is only available for equal and not_equal? Or might it be as (relatively) simple as defining an inner loop for void type only for those two?

  10. charris commented on May 23, 2017

    @charris
    Member

    It would solve the __array_priority__ and __array_ufunc__=None override problems though. That would be a good start and something I wouldn't mind having in 1.13.

  11. mhvk commented on May 23, 2017

    @mhvk
    ContributorAuthor

    @charris - OK, that makes sense: a PR just covering the high array priority and array ufunc is None case is in #9167. If we go that route, what remains will just be for an array like that defines __array_ufunc__ as a proper function; probably best to open a new issue for it (once #9167 is in).

  12. removed this from the 1.13.0 release milestone on May 24, 2017
  13. mhvk commented on May 26, 2017

    @mhvk
    ContributorAuthor

    Updated the text at the top to reflect that even with #9167 the issue remains that an array-like cannot override __eq__ for structured arrays by using __array_ufunc__.

  14. mhvk commented on Jan 11, 2024

    @mhvk
    ContributorAuthor

    Closing this, since it is possible to avoid by setting __array_ufunc__ = None to explicitly opt out of ndarray.__eq__ taking over.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions