1.. currentmodule:: numpy.random
2
3.. _extending:
4
5Extending
6---------
7The BitGenerators have been designed to be extendable using standard tools for
8high-performance Python -- numba and Cython.  The `~Generator` object can also
9be used with user-provided BitGenerators as long as these export a small set of
10required functions.
11
12Numba
13=====
14Numba can be used with either CTypes or CFFI.  The current iteration of the
15BitGenerators all export a small set of functions through both interfaces.
16
17This example shows how numba can be used to produce gaussian samples using
18a pure Python implementation which is then compiled.  The random numbers are
19provided by ``ctypes.next_double``.
20
21.. literalinclude:: ../../../../numpy/random/_examples/numba/extending.py
22    :language: python
23    :end-before: example 2
24
25Both CTypes and CFFI allow the more complicated distributions to be used
26directly in Numba after compiling the file distributions.c into a ``DLL`` or
27``so``.  An example showing the use of a more complicated distribution is in
28the `examples` section below.
29
30.. _random_cython:
31
32Cython
33======
34
35Cython can be used to unpack the ``PyCapsule`` provided by a BitGenerator.
36This example uses `PCG64` and the example from above.  The usual caveats
37for writing high-performance code using Cython -- removing bounds checks and
38wrap around, providing array alignment information -- still apply.
39
40.. literalinclude:: ../../../../numpy/random/_examples/cython/extending_distributions.pyx
41    :language: cython
42    :end-before: example 2
43
44The BitGenerator can also be directly accessed using the members of the ``bitgen_t``
45struct.
46
47.. literalinclude:: ../../../../numpy/random/_examples/cython/extending_distributions.pyx
48    :language: cython
49    :start-after: example 2
50    :end-before: example 3
51
52Cython can be used to directly access the functions in
53``numpy/random/c_distributions.pxd``. This requires linking with the
54``npyrandom`` library located in ``numpy/random/lib``.
55
56.. literalinclude:: ../../../../numpy/random/_examples/cython/extending_distributions.pyx
57    :language: cython
58    :start-after: example 3
59
60See :ref:`extending_cython_example` for the complete listings of these examples
61and a minimal ``setup.py`` to build the c-extension modules.
62
63CFFI
64====
65
66CFFI can be used to directly access the functions in
67``include/numpy/random/distributions.h``. Some "massaging" of the header
68file is required:
69
70.. literalinclude:: ../../../../numpy/random/_examples/cffi/extending.py
71    :language: python
72    :end-before: dlopen
73
74Once the header is parsed by ``ffi.cdef``, the functions can be accessed
75directly from the ``_generator`` shared object, using the `BitGenerator.cffi` interface.
76
77.. literalinclude:: ../../../../numpy/random/_examples/cffi/extending.py
78    :language: python
79    :start-after: dlopen
80
81
82New Bit Generators
83==================
84`~Generator` can be used with user-provided `~BitGenerator`\ s. The simplest
85way to write a new BitGenerator is to examine the pyx file of one of the
86existing BitGenerators. The key structure that must be provided is the
87``capsule`` which contains a ``PyCapsule`` to a struct pointer of type
88``bitgen_t``,
89
90.. code-block:: c
91
92  typedef struct bitgen {
93    void *state;
94    uint64_t (*next_uint64)(void *st);
95    uint32_t (*next_uint32)(void *st);
96    double (*next_double)(void *st);
97    uint64_t (*next_raw)(void *st);
98  } bitgen_t;
99
100which provides 5 pointers. The first is an opaque pointer to the data structure
101used by the BitGenerators.  The next three are function pointers which return
102the next 64- and 32-bit unsigned integers, the next random double and the next
103raw value.  This final function is used for testing and so can be set to
104the next 64-bit unsigned integer function if not needed. Functions inside
105``Generator`` use this structure as in
106
107.. code-block:: c
108
109  bitgen_state->next_uint64(bitgen_state->state)
110
111Examples
112========
113
114.. toctree::
115    Numba <examples/numba>
116    CFFI + Numba <examples/numba_cffi>
117    Cython <examples/cython/index>
118    CFFI <examples/cffi>
119