BUG: core: ensure __r*__ has precedence over __numpy_ufunc__

Add a special case to the implementation of ndarray.__mul__ et al. that refuses to work on other objects that are not ndarray subclasses and implement both __numpy_ufunc__ and __r*__.

This way, execution passes first to the custom __r*__ method, which makes it possible to have e.g. __mul__ and np.multiply do different things.

Additionally, disable one __array_priority__ special case handling when also __numpy_ufunc__ is defined (which may have been the reason why __rmul__ continued to work in scipy.sparse matrices).

Addresses gh-3812

Feedback welcome --- I think this solves the issue without being too magical, but YMMV