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