User-defined Bit Generators¶
Most bit generators use Cython to wrap an implementation in C. While this
method leads to best case performance, it is necessarily involved.
UserBitGenerator
allows bit generators to be
written in Python (slow) or numba (fast) or for existing PRNGs to be
wrapped. The bit generator can then be used with a
Generator
. See the demonstration notebook for
examples.
-
class randomgen.wrapper.UserBitGenerator(next_raw, bits=
64
, next_64=None
, next_32=None
, next_double=None
, state=None
, state_getter=None
, state_setter=None
)¶ Construct a bit generator from Python functions
- Parameters:¶
- next_raw¶
A callable that returns either 64 or 32 random bits. It must accept a single input which is a void pointer to a memory address.
- bits=
64
¶ The number of bits output by the next_raw callable. Must be either 32 or 64.
- next_64=
None
¶ A callable with the same signature as as next_raw that always return 64 bits. If not provided, this function is constructed using next_raw.
- next_32=
None
¶ A callable with the same signature as as next_raw that always return 32 bits. If not provided, this function is constructed using next_raw.
- next_double=
None
¶ A callable with the same signature as as next_raw that always return a random double in [0,1). If not provided, this function is constructed using next_raw.
- state=
None
¶ A ctypes pointer to pass into the next functions. In most cases this should be None, in which case the null pointer is passed.
- state_getter=
None
¶ A callable that returns the state of the bit generator. If not provided, getting the
state
property will raise NotImplementedError.- state_setter=
None
¶ A callable that sets the state of the bit generator. Must take a single input. If not provided, getting the
state
property will raise NotImplementedError.
Notes
There is one key caveat when using a UserBitGenerator. The callable must run without exceptions.
Warning
It is essential that the callable function runs without producing an Exception. Exceptions will be silently ignored and the generator will produce incorrect results.
Examples
A generator that rotates across 4 values from random.org.
>>> import numpy as np >>> rv = np.array([ 7713239619832409074, 17318243661941184039, ... 14412717025735663865, 521015634160378615, 0], ... dtype=np.uint64) >>> def next_raw(voidp): ... idx = int(rv[-1] % 4) ... out = rv[idx] ... rv[-1] += 1 ... return int(out) >>> bg = UserBitGenerator(next_raw)
See the documentation for a more realistic example.
From Low-level Objects¶
|
from_cfunc(next_raw, next_64, next_32, next_double, state, |
|
from_ctypes(next_raw, next_64, next_32, next_double, state, |
State¶
Get or set the state |
Extending¶
CFFI interface |
|
ctypes interface |
Testing¶
|
Return randoms as generated by the underlying BitGenerator |