Skip to content

BUG: Operator equal supports void and np.equal does not #9147

Closed

Description

@eric-wieser
>>> x = np.array([(0, 1, 0)] * 10, dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')])
>>> x == x
array([ True,  True,  True,  True,  True,  True,  True,  True,  True,  True], dtype=bool)
>>> np.equal(x, x)
FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison
NotImplemented

Presumably this has ramifications for users overloading __array_ufunc__ with @shoyer's mixin class, causing operations to fail on structured dtypes - as these do not pass through ndarray.__eq__, which seems to special case things to make them work

Activity

  1. shoyer commented on May 20, 2017

    @shoyer
    Member

    I think this is an unintended and/or unforeseen consequence of a partial fix for issues with == in old versions of numpy (see #5964).

    As you can see, this deprecation notice went in about two years ago now (NumPy 1.10). Can we finally fix the broken behavior? It seems like we've given more than enough warning to anyone who may have been relying on the old broken behavior.

  2. charris commented on May 20, 2017

    @charris
    Member

    @shoyer The 1.10 deprecations/futurwarnings will expire in 1.14. There are several that I will be putting in a PR soonish to change.

  3. seberg commented on May 21, 2017

    @seberg
    Member

    ufuncs currently don't support flexible types, so string and voids are specifically handled by __eq__ and not send to np.equal.

  4. mhvk commented on May 21, 2017

    @mhvk
    Contributor

    The special handling gets the elements and compares them in turn -- and those comparisons do get send to any __array_ufunc__, as does the combination of them via logical_and, so from that perspective it is OK at least for ndarray subclasses.

    For array-likes it is perhaps not unreasonable for the mixin to not try to also support structured array-likes in a similar way. Though it would be good to document this.

  5. mhvk commented on May 21, 2017

    @mhvk
    Contributor

    Looking in more detail at the source for array_richcompare at Py_EQ ( https://github.com/numpy/numpy/blob/master/numpy/core/src/multiarray/arrayobject.c#L1302), I see that the RICHCMP_GIVE_UP_IF_NEEDED comes after the check for void, rather than before, which seems wrong. See new issue #9153.

    Similarly, the check for string comes even before any of this, which may also not be quite right. Looking in detail, it falls through if other is not also a string-like array, so this case works for array-likes. And for subclasses, since the ufunc doesn't work for strings, I guess one has little choice but to do what is done there; subclasses can override simply by defining __eq__ and their __eq__ will get called.

  6. ahaldane commented on Dec 5, 2018

    @ahaldane
    Member

    Just want to say that I just hit this bug while trying to implement np.equal in __array_ufunc__ for my Masked-ducktype. More in detail, my ducktype inherits from numpy.lib.mixins.NDArrayOperatorsMixin which implements __eq__ = _binary_method(um.equal, 'eq'). In other words it assumes __eq__ can be replaced by np.equal, however this bug means that is not true for structured arrays.

    So anybody who uses NDArrayOperatorsMixin probably can't handle structured arrays currently.

  7. mhvk commented on Dec 6, 2018

    @mhvk
    Contributor

    Yes, structured arrays are a bit of a step-child currently, with the difficulty of defining ufuncs for them

  8. changed the title [-]BUG: Operator equals works where np.equal does not[/-] [+]BUG: Operator equal supports `void` and np.equal does not[/+] on Dec 7, 2022
  9. seberg commented on Dec 7, 2022

    @seberg
    Member

    Changed the title, strings are in the ufunc now. Void could be moved, although it is a bit of a smaller project to do so.
    A new difference is that == will return an array of all False when dtypes cannot be compared while np.equal() errors.

  10. mattip commented on Jul 22, 2026

    @mattip
    Member

    Closing this as stale.

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