Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2519585

Browse files
authored
DOC: Document Cython and Numba as ways of generating ufuncs (#31541)
1 parent 55460a7 commit 2519585

1 file changed

Lines changed: 91 additions & 0 deletions

File tree

doc/source/user/c-info.ufunc-tutorial.rst

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,3 +874,94 @@ Sample usage::
874874
>>> npufunc.add_triplet(a, a)
875875
array([(2, 4, 6), (8, 10, 12)],
876876
dtype=[('f0', '<u8'), ('f1', '<u8'), ('f2', '<u8')])
877+
878+
Alternatives to writing your own ufunc
879+
======================================
880+
881+
While most people like the speed benefits that come from writing a ufunc
882+
using the Numpy C API, not everyone enjoys writing C code. Fortunately
883+
there are a few alternatives that can create ufuncs with C-like speed
884+
but without having to understand the Numpy C API.
885+
886+
Numba
887+
-----
888+
889+
The `Numba vectorize decorator
890+
<https://numba.readthedocs.io/en/stable/user/vectorize.html>`_ provides
891+
a quick way to compile a subset of Python to an accelerated function that
892+
behaves like a ufunc. It can be used without arguments to support any
893+
numeric type (compiled on a "just in time" basis as you use them):
894+
895+
.. code-block:: python
896+
897+
import numba as nb
898+
899+
@nb.vectorize
900+
def logit(p):
901+
return log(p/(1-p))
902+
903+
or with arguments to support only specific numeric types (compiled when
904+
you define the function):
905+
906+
.. code-block:: python
907+
908+
import numba as nb
909+
910+
@nb.vectorize([nb.int32(nb.int32),
911+
nb.int64(nb.int64),
912+
nb.float32(nb.float32),
913+
nb.float64(nb.float64)])
914+
def logit(p):
915+
return log(p/(1-p))
916+
917+
In addition to simple ufuncs, Numba can also be used to generate
918+
generalized ufuncs in a very similar way.
919+
920+
Numba is a run-time dependency (i.e. users of your library will need to
921+
have Numba installed), and the way that it dynamically compiles the ufuncs
922+
can cause a noticeable pause either on import or the first time you use
923+
a function with a particular set of argument types.
924+
925+
One (usually) minor detail is that Numba ufuncs are not "true" Numpy
926+
ufuncs. This would normally only matter if you try to use them as a
927+
:c:type:`PyUFuncObject` from within C. They support most of the same
928+
behavior as Numpy ufuncs, including the ``__array_ufunc__``
929+
interoperability protocol that lets them handle other array types.
930+
931+
Cython
932+
------
933+
934+
Cython provides a `ufunc decorator
935+
<https://cython.readthedocs.io/en/latest/src/userguide/numpy_ufuncs.html>`_
936+
which can transform functions written with Python-like syntax into
937+
Numpy ufuncs. For example:
938+
939+
.. code-block:: cython
940+
941+
cimport cython
942+
from libc.math cimport log
943+
944+
@cython.ufunc
945+
@cython.cdivision(True)
946+
cdef double logit(double p) noexcept:
947+
return log(p/(1-p))
948+
949+
Here ``log`` is taken from the C standard library. The ``cdivision``
950+
dectorator and ``noexcept`` exception specification are Cython extensions
951+
and ensure that a divide by zero will not raise a Python exception.
952+
They are useful for this specific example but not necessary for ufuncs
953+
generally.
954+
955+
To support multiple numeric types, use "fused types" as the argument types
956+
or return types (in the example above, ``double`` could be replaced with
957+
``cython.numeric`` to support the most widely available standard C integer,
958+
floating and complex numeric types).
959+
960+
Cython functions need to be compiled ahead of time (and thus Cython is
961+
a compile-time dependency, but users of your function do not need to
962+
have Cython installed themselves). Numpy will be both a compile-time and
963+
a runtime dependency for your compiled module, since Cython itself uses
964+
the ufunc C API described earlier in this section.
965+
966+
As of May 2026, only simple ufuncs are supported and generalized ufuncs
967+
are not yet supported.

0 commit comments

Comments
 (0)