On Thu, 2025-01-02 at 10:17 -0600, Jim Pivarski wrote: > In preparing my email, I was looking for a way to identify a ufunc, > other > than `isinstance`, since `np.vectorize` and `nb.vectorize` make > objects > that behave like ufuncs (even obeying NEP 13 semantics, checking for > `__array_ufunc__`), but they don't inherit from the `np.ufunc` type. > I was > thinking that a "ufunc" might be defined as a protocol, like Python's > `Sequence` or `Mapping`. > > I couldn't find a way to do that, particularly because the desired > features > of a ufunc involve more than having particular methods—they need to > check > their arguments and call particular methods: `__array_ufunc__`. > That's not > something one can check with `hasattr`. > > Sebastian, are you saying that the only definition of "ufunc" is that > it > inherits from `np.ufunc`? As far as I know, the only way to do that > is by > implementing it in C (and maybe even depend on a version of the NumPy > ABI). > But it's useful for libraries other than NumPy to be able to define > ufuncs, > starting with SciPy, which defines a lot of them.
Yes, I am saying that. I think `np.vectorize` mimics gufuncs (if a gufunc) and `np.frompyfunc` creates a real ufunc. There was always some discussion about allowing to create a "C ufunc" that is implemented in Python (including gufuncs). That works, but is a little bit more raw than one might expect (basically, array data ownership must be limited to the function and we have no way to enforce that). As for a protocol.... Maybe, but not sure. Another thing I think we should add anyway is a "I do everything" path in a ufunc. And once you have that, the main thing that C-side ufunc implementation (or wrapper at that point?) would probably be: 1. Figure out any necessary `__array_ufunc__` things. 2. Decide on the result DType and select the appropriate implementation (which could be a single implementation that is always used). One downside of this is, that NumPy ufuncs have the abstraction that allows them to work on non-NumPy arrays (and no, I don't mean via `__array_ufunc__`, I mean that awkward array could low-level call the 1-D internal loop in principle). And if you "do everything" in a Python function, you may lose that part. In practice, that probably doesn't matter much, though. Even if awkward-array starts using this, it's probably a thing to figure out then how to deal with it. As a protocol only? Maybe. I haven't thought about it, the above might cover most things and also allow a few nice low-level nice tricks maybe. (I am thinking e.g. of a just in time compiled ufunc kernel for the specific array dimensions that e.g. also inlines casting. Or a gufunc that pushes work to a GPU, although in most cases maybe we wouldn't even need this.) - Sebastian > > Are there any plans to define "ufunc" as a protocol, rather than a > type > that must be inherited to be recognized? Its behaviors are well > defined at > this point. > > Jim > > > On Thu, Jan 2, 2025, 5:41 AM Sebastian Berg > <sebast...@sipsolutions.net> > wrote: > > > Stack is not a generalized ufunc. > > > > It may behave similar to one in many ways, but implementation wise > > has > > nothing to do with ufuncs. > > Also ufuncs do not support an arbitrary number of operands. > > > > `vectorize` can indeed mimic generalized ufuncs, but > > (unfortunately) > > doesn't create them as such currently. > > > > - Sebastian > > > > > > On Tue, 2024-12-31 at 10:20 -0600, Jim Pivarski via NumPy- > > Discussion > > wrote: > > > I think you're right: the function `stack`, as you've defined it, > > > is > > > a > > > gufunc. > > > > > > Here's an implementation using np.vectorize > > > < > > > https://numpy.org/doc/stable/reference/generated/numpy.vectorize.html > > > > > > > (rather than nb.vectorize > > > <https://numba.readthedocs.io/en/stable/user/vectorize.html>). > > > Since > > > the > > > signature is not "()->()" or "(),()->()" (or similar with a > > > different > > > number of scalar inputs and scalar outputs), it's a generalized > > > ufunc. > > > > > > > > > def stack(a, b): > > > > > > ... broadcasts = np.broadcast_arrays(a, b) > > > > > > ... return np.stack(broadcasts, axis=-1) > > > > > > ... > > > > > > > > > stacky = np.vectorize(stack, signature="(),()->(2)") > > > > > > > > > stacky(np.arange(5), np.arange(5)) > > > > > > array([[0, 0], > > > > > > [1, 1], > > > > > > [2, 2], > > > > > > [3, 3], > > > > > > [4, 4]]) > > > > > > > > > stacky(np.arange(5), np.array([[1], [2], [3], [4], [5]])) > > > > > > array([[[0, 1], > > > > > > [1, 1], > > > > > > [2, 1], > > > > > > [3, 1], > > > > > > [4, 1]], > > > > > > > > > [[0, 2], > > > > > > [1, 2], > > > > > > [2, 2], > > > > > > [3, 2], > > > > > > [4, 2]], > > > > > > > > > [[0, 3], > > > > > > [1, 3], > > > > > > [2, 3], > > > > > > [3, 3], > > > > > > [4, 3]], > > > > > > > > > [[0, 4], > > > > > > [1, 4], > > > > > > [2, 4], > > > > > > [3, 4], > > > > > > [4, 4]], > > > > > > > > > [[0, 5], > > > > > > [1, 5], > > > > > > [2, 5], > > > > > > [3, 5], > > > > > > [4, 5]]]) > > > > > > > > > > > > On Tue, Dec 31, 2024 at 2:44 AM john.a.dawson--- via NumPy- > > > Discussion > > > < > > > numpy-discussion@python.org> wrote: > > > > > > > Is the function `stack` above a gufunc? > > > > _______________________________________________ > > > > NumPy-Discussion mailing list -- numpy-discussion@python.org > > > > To unsubscribe send an email to > > > > numpy-discussion-le...@python.org > > > > https://mail.python.org/mailman3/lists/numpy-discussion.python.org/ > > > > Member address: jpivar...@gmail.com > > > > > > > _______________________________________________ > > > NumPy-Discussion mailing list -- numpy-discussion@python.org > > > To unsubscribe send an email to numpy-discussion-le...@python.org > > > https://mail.python.org/mailman3/lists/numpy-discussion.python.org/ > > > Member address: sebast...@sipsolutions.net > > > > _______________________________________________ NumPy-Discussion mailing list -- numpy-discussion@python.org To unsubscribe send an email to numpy-discussion-le...@python.org https://mail.python.org/mailman3/lists/numpy-discussion.python.org/ Member address: arch...@mail-archive.com