[Numpy-discussion] Re: Is a Python function a gufunc if it broadcasts its arguments appropriately?

2025-01-02 Thread Sebastian Berg
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
> ). 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


[Numpy-discussion] Re: Is a Python function a gufunc if it broadcasts its arguments appropriately?

2025-01-02 Thread Jim Pivarski via NumPy-Discussion
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.

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 
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
> > ). 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