Re: Do special functions need to have all kwargs/attributes/methods of ufuncs?

Albert Steppi <[email protected]> Wed, 20 Sep 2023 16:29:43 -0400
Newsgroups gmane.comp.python.scientific.devel
Message-ID <CAPceVpWe638-ULNg-QJsutxY-y6xcUEQpGyO99aPMsM=LmjWLg@mail.gmail.com>
It should be straightforward if a little tedious to add support for the
ufunc attributes like `nin`, `nout`, etc. and ufunc methods like `reduce`,
`accumulate`, etc. (for numpy and raising an error for backends that don't
support these methods), if not doing so would require a difficult
deprecation cycle. I think making something like isinstance(special.ndtr,
np.ufunc) work would require some pretty ugly hackery, so I'd prefer to at
least break this.

I can't see a serious use for `reduce`, `accumulate`, and `reduceat` for
special functions, but `outer` and `at` could be useful in some cases.
Based on the documentation Robert Kern linked to, I think it would probably
be best to support all ufunc attributes and methods.

Albert

On Tue, Sep 19, 2023 at 12:30 PM Robert Kern <[email protected]> wrote:

> On Tue, Sep 19, 2023 at 12:00 PM Matt Haberland <[email protected]>
> wrote:
>
>> Yes, the documentation mentions that they are "technically" ufuncs. My
>> comment was about documentation of the features of ufuncs - the
>> documentation seems to intentionally hide all ufunc parameters from the
>> signature. Please see
>> https://github.com/scipy/scipy/pull/19023#issuecomment-1711949107
>> for further context.
>>
>
> More out of concision and deduplication than anything else because those
> parameters are documented in `ufunc` itself.
>
> ```
> |2> special.ndtr?
> Call signature:  special.ndtr(*args, **kwargs)
> Type:            ufunc
> String form:     <ufunc 'ndtr'>
> File:
>  ~/.edm/envs/py38/lib/python3.8/site-packages/numpy/__init__.py
> Docstring:
> ndtr(x, /, out=None, *, where=True, casting='same_kind', order='K',
> dtype=None, subok=True[, signature, extobj])
>
> ndtr(x)
>
> Gaussian cumulative distribution function.
>
> Returns the area under the standard Gaussian probability
> density function, integrated from minus infinity to `x`
>
> .. math::
>
>    \frac{1}{\sqrt{2\pi}} \int_{-\infty}^x \exp(-t^2/2) dt
>
> Parameters
> ----------
> x : array_like, real or complex
>     Argument
>
> Returns
> -------
> ndarray
>     The value of the normal CDF evaluated at `x`
>
> See Also
> --------
> erf
> erfc
> scipy.stats.norm
> log_ndtr
> Class docstring:
> Functions that operate element by element on whole arrays.
>
> To see the documentation for a specific ufunc, use `info`.  For
> example, ``np.info(np.sin)``.  Because ufuncs are written in C
> (for speed) and linked into Python with NumPy's ufunc facility,
> Python's help() function finds this page whenever help() is called
> on a ufunc.
>
> A detailed explanation of ufuncs can be found in the docs for
> :ref:`ufuncs`.
>
> **Calling ufuncs:** ``op(*x[, out], where=True, **kwargs)``
>
> Apply `op` to the arguments `*x` elementwise, broadcasting the arguments.
>
> The broadcasting rules are:
>
> * Dimensions of length 1 may be prepended to either array.
> * Arrays may be repeated along dimensions of length 1.
>
> Parameters
> ----------
> *x : array_like
>     Input arrays.
> out : ndarray, None, or tuple of ndarray and None, optional
>     Alternate array object(s) in which to put the result; if provided, it
>     must have a shape that the inputs broadcast to. A tuple of arrays
>     (possible only as a keyword argument) must have length equal to the
>     number of outputs; use None for uninitialized outputs to be
>     allocated by the ufunc.
> where : array_like, optional
>     This condition is broadcast over the input. At locations where the
>     condition is True, the `out` array will be set to the ufunc result.
>     Elsewhere, the `out` array will retain its original value.
>     Note that if an uninitialized `out` array is created via the default
>     ``out=None``, locations within it where the condition is False will
>     remain uninitialized.
> **kwargs
>     For other keyword-only arguments, see the :ref:`ufunc docs
> <ufuncs.kwargs>`.
>
> Returns
> -------
> r : ndarray or tuple of ndarray
>     `r` will have the shape that the arrays in `x` broadcast to; if `out`
> is
>     provided, it will be returned. If not, `r` will be allocated and
>     may contain uninitialized values. If the function has more than one
>     output, then the result will be a tuple of arrays.
> ```
>
> That's as much the official docs for this object as what appears on
> docs.scipy.org.
>
> These are ufuncs. They should be ufuncs regardless of the environment
> variable. If you want to change them from being ufuncs to just being
> elementwise functions, go through a big deprecation where they are *never*
> ufuncs regardless of environment variable (i.e. plain functions with the
> docs.scipy.org signatures and just use the ufunc implementations
> underneath when the Array API is `numpy`). But I suspect one can also
> implement a ufunc-like override object that passes through all attribute
> access and ufunc-only keyword calls to the ufunc object and calls the
> override elementwise function only when it fits.
>
> --
> Robert Kern
> _______________________________________________
> SciPy-Dev mailing list -- [email protected]
> To unsubscribe send an email to [email protected]
> https://mail.python.org/mailman3/lists/scipy-dev.python.org/
> Member address: [email protected]
>

_______________________________________________
SciPy-Dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/scipy-dev.python.org/
Member address: [email protected]