Adding vectorized ufuncs in scipy.special#

Many of the functions in special are vectorized versions of scalar functions. The scalar functions are written by hand and the necessary loops for vectorization are generated automatically. This section discusses the steps necessary to add a new vectorized special function.

The first step in adding a new vectorized function is writing the corresponding scalar function. This can be done in Cython, C, C++, or Fortran. If starting from scratch then Cython should be preferred because the code is easier to maintain for developers only familiar with Python. If the primary code is in Fortran then it is necessary to write a C wrapper around the code; for examples of such wrappers see specfun_wrappers.c.

After implementing the scalar function, register the new function by adding an entry to functions.json. The docstring in generate_ufuncs.py explains the format. Also add documentation for the new function by adding an entry to add_newdocs.py; look in the file for examples.

When writing the parameters section of the documentation for ufuncs, the type of an argument should be array_like. Discussion of whether an argument can be e.g. real or complex-valued should be saved for the description. So for example, if we were to document the parameters for the Gamma function then it should look like this:

Parameters
----------
z : array_like
    Real or complex valued argument

When documenting the returns section, the type of the returned value should be scalar or ndarray since ufuncs return scalars when given scalars as arguments. Also keep in mind that providing a name for the return value is optional, and indeed is often not helpful for special functions. So for the Gamma function we might have something like this:

Returns
-------
scalar or ndarray
    Values of the Gamma function