Skip to content

Commit 6c97fd7

Browse files
Sheppard, KevinSheppard, Kevin
authored andcommitted
ENH: Add direct access to system crypto RNG
Add direct access to the system crypto generator Add docstrings for xorshift and pcg RNGs
1 parent a107f72 commit 6c97fd7

File tree

11 files changed

+222
-74
lines changed

11 files changed

+222
-74
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ It is essentially complete. There are a few rough edges that need to be smoothe
3939
* Document core RNG classes
4040
* Pickling support
4141
* Verify entropy based initialization is missing for some RNGs
42-
* Add direct access to the system cryptographic random number generator
4342
* Multiple stream support for MLFG and MRG32K3A
4443
* Creation of additional streams from a RandomState where supported (i.e.
4544
a `next_stream()` method)

randomstate/interface.pyx

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
11
#!python
22
#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True
33
import sys
4-
import numpy as np
5-
cimport numpy as np
6-
cimport cython
74
import operator
8-
from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t
9-
from cpython cimport Py_INCREF
105
try:
116
from threading import Lock
127
except:
138
from dummy_threading import Lock
9+
10+
import numpy as np
11+
cimport numpy as np
12+
cimport cython
13+
from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t
14+
from cpython cimport Py_INCREF
15+
16+
from binomial cimport binomial_t
17+
from cython_overrides cimport PyFloat_AsDouble, PyInt_AsLong, PyErr_Occurred, PyErr_Clear
18+
1419
np.import_array()
1520

16-
cdef extern from "Python.h":
17-
double PyFloat_AsDouble(object ob)
18-
long PyInt_AsLong(object ob)
19-
int PyErr_Occurred()
20-
void PyErr_Clear()
21+
#cdef extern from "Python.h":
22+
# double PyFloat_AsDouble(object ob)
23+
# long PyInt_AsLong(object ob)
24+
# int PyErr_Occurred()
25+
# void PyErr_Clear()
2126

2227
include "config.pxi"
23-
include "src/common/binomial.pxi"
28+
#include "src/common/binomial.pxi"
2429

2530
IF RNG_NAME == 'pcg32':
2631
include "shims/pcg-32/pcg-32.pxi"
@@ -108,9 +113,55 @@ cdef extern from "distributions.h":
108113
cdef void random_bounded_uint8_fill(aug_state *state, uint8_t off, uint8_t rng, int cnt, uint8_t *out) nogil
109114
cdef void random_bool_fill(aug_state *state, int8_t off, int8_t rng, int cnt, int8_t *out) nogil
110115

116+
cdef void entropy_fill(void *dest, size_t size)
117+
cdef bint entropy_getbytes(void* dest, size_t size)
118+
111119
include "array_utilities.pxi"
112120
include "bounded_integers.pxi"
113121

122+
def read_entropy(size=None):
123+
"""
124+
Read entropy from the system cryptographic provider
125+
126+
Parameters
127+
----------
128+
size : int or tuple of ints, optional
129+
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
130+
``m * n * k`` samples are drawn. Default is None, in which case a
131+
single value is returned.
132+
133+
Returns
134+
-------
135+
entropy : scalar or ndarray
136+
Entropy bits in 32-bit unsigned integers
137+
138+
Notes
139+
-----
140+
On Unix-like machines, reads from /dev/urandom. On Windows machines reads
141+
from the RSA Full cryptographic service provider.
142+
143+
Raises RuntimeError if the command fails.
144+
"""
145+
cdef bint success
146+
cdef size_t n = 0
147+
cdef uint32_t random = 0
148+
cdef uint32_t [:] randoms
149+
150+
if size is None:
151+
success = entropy_getbytes(<void *>&random, 4)
152+
else:
153+
n = compute_numel(size)
154+
randoms = np.zeros(n, dtype=np.uint32)
155+
print(n)
156+
success = entropy_getbytes(<void *>(&randoms[0]), 4 * n)
157+
if not success:
158+
raise RuntimeError('Unable to read from system cryptographic provider')
159+
160+
if n == 0:
161+
return random
162+
return np.asarray(randoms).reshape(size)
163+
164+
114165
cdef double kahan_sum(double *darr, np.npy_intp n):
115166
cdef double c, y, t, sum
116167
cdef np.npy_intp i

randomstate/shims/pcg-32/pcg-32.pxi

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,55 @@ cdef object _set_state(aug_state state, object state_info):
3939
state.rng.inc = state_info[1]
4040

4141
DEF CLASS_DOCSTRING = """
42-
This is the pcg32 docstring.
43-
"""
42+
RandomState(seed=None)
43+
44+
Container for the PCG-32 pseudo random number generator.
45+
46+
PCG-32 is a 64-bit implementation of O'Neill's permutation congruential
47+
generator ([1]_, [2]_). PCG-32 has a period of 2**64 and supports advancing
48+
an arbitrary number of steps as well as 2**63 streams.
49+
50+
`pcg32.RandomState` exposes a number of methods for generating random
51+
numbers drawn from a variety of probability distributions. In addition to the
52+
distribution-specific arguments, each method takes a keyword argument
53+
`size` that defaults to ``None``. If `size` is ``None``, then a single
54+
value is generated and returned. If `size` is an integer, then a 1-D
55+
array filled with generated values is returned. If `size` is a tuple,
56+
then an array with that shape is filled and returned.
57+
58+
*No Compatibility Guarantee*
59+
'pcg32.RandomState' does not make a guarantee that a fixed seed and a
60+
fixed series of calls to 'pcg32.RandomState' methods using the same
61+
parameters will always produce the same results. This is different from
62+
'numpy.random.RandomState' guarantee. This is done to simplify improving
63+
random number generators. To ensure identical results, you must use the
64+
same release version.
65+
66+
Parameters
67+
----------
68+
seed : {None, long}, optional
69+
Random seed initializing the pseudo-random number generator.
70+
Can be an integer in [0, 2**64] or ``None`` (the default).
71+
If `seed` is ``None``, then `xorshift1024.RandomState` will try to read data
72+
from ``/dev/urandom`` (or the Windows analogue) if available or seed from
73+
the clock otherwise.
74+
inc : {None, int}, optional
75+
Stream to return.
76+
Can be an integer in [0, 2**64] or ``None`` (the default). If `inc` is
77+
``None``, then 1 is used. Can be used with the same seed to
78+
produce multiple streams using other values of inc.
79+
80+
Notes
81+
-----
82+
Supports the method advance to advance the PRNG an arbitrary number of steps.
83+
The state of the PCG-32 PRNG is represented by 2 64-bit integers.
84+
85+
See pcg64 for a similar implementation with a larger period.
86+
87+
References
88+
----------
89+
.. [1] "PCG, A Family of Better Random Number Generators",
90+
http://www.pcg-random.org/
91+
.. [2] O'Neill, Melissa E. "PCG: A Family of Simple Fast Space-Efficient
92+
Statistically Good Algorithms for Random Number Generation"
93+
"""
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
DEF CLASS_DOCSTRING = """
2+
RandomState(seed=None)
3+
4+
Container for the PCG-64 pseudo random number generator.
5+
6+
PCG-64 is a 128-bit implementation of O'Neill's permutation congruential
7+
generator ([1]_, [2]_). PCG-64 has a period of 2**128 and supports advancing
8+
an arbitrary number of steps as well as 2**127 streams.
9+
10+
`pcg64.RandomState` exposes a number of methods for generating random
11+
numbers drawn from a variety of probability distributions. In addition to the
12+
distribution-specific arguments, each method takes a keyword argument
13+
`size` that defaults to ``None``. If `size` is ``None``, then a single
14+
value is generated and returned. If `size` is an integer, then a 1-D
15+
array filled with generated values is returned. If `size` is a tuple,
16+
then an array with that shape is filled and returned.
17+
18+
*No Compatibility Guarantee*
19+
'pcg64.RandomState' does not make a guarantee that a fixed seed and a
20+
fixed series of calls to 'pcg64.RandomState' methods using the same
21+
parameters will always produce the same results. This is different from
22+
'numpy.random.RandomState' guarantee. This is done to simplify improving
23+
random number generators. To ensure identical results, you must use the
24+
same release version.
25+
26+
Parameters
27+
----------
28+
seed : {None, long}, optional
29+
Random seed initializing the pseudo-random number generator.
30+
Can be an integer in [0, 2**128] or ``None`` (the default).
31+
If `seed` is ``None``, then `xorshift1024.RandomState` will try to read data
32+
from ``/dev/urandom`` (or the Windows analogue) if available or seed from
33+
the clock otherwise.
34+
inc : {None, int}, optional
35+
Stream to return.
36+
Can be an integer in [0, 2**128] or ``None`` (the default). If `inc` is
37+
``None``, then 1 is used. Can be used with the same seed to
38+
produce multiple streams using other values of inc.
39+
40+
Notes
41+
-----
42+
Supports the method advance to advance the PRNG an arbitrary number of steps.
43+
The state of the PCG-64 PRNG is represented by 2 128-bit integers.
44+
45+
See pcg32 for a similar implementation with a smaller period.
46+
47+
References
48+
----------
49+
.. [1] "PCG, A Family of Better Random Number Generators",
50+
http://www.pcg-random.org/
51+
.. [2] O'Neill, Melissa E. "PCG: A Family of Simple Fast Space-Efficient
52+
Statistically Good Algorithms for Random Number Generation"
53+
"""

randomstate/shims/pcg-64/pcg-64-emulated.pxi

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,4 @@ cdef object _set_state(aug_state state, object state_info):
5555
state.rng.state = pcg128_from_pylong(state_info[0])
5656
state.rng.inc = pcg128_from_pylong(state_info[1])
5757

58-
DEF CLASS_DOCSTRING = """
59-
This is the pcg64 docstring.
60-
"""
58+
include "pcg-64-docstring.pxi"

randomstate/shims/pcg-64/pcg-64.pxi

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,4 @@ cdef object _set_state(aug_state state, object state_info):
4343
state.rng.state = state_info[0]
4444
state.rng.inc = state_info[1]
4545

46-
DEF CLASS_DOCSTRING = """
47-
This is the pcg64 docstring.
48-
"""
46+
include "pcg-64-docstring.pxi"

randomstate/shims/xorshift1024/xorshift1024.pxi

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,48 @@ cdef object _set_state(aug_state state, object state_info):
4747
state.rng.s[i] = key[i]
4848
state.rng.p = state_info[1]
4949

50+
5051
DEF CLASS_DOCSTRING = """
51-
This is the xorshift1024 docstring.
52+
RandomState(seed=None)
53+
54+
Container for the xorshift1024* pseudo random number generator.
55+
56+
xorshift1024* is a 64-bit implementation of Saito and Matsumoto's XSadd
57+
generator [1]_. xorshift1024* has a period of 2**1024 - 1 and supports jumping
58+
the sequence in increments of 2**512, which allow multiple non-overlapping
59+
sequences to be generated.
60+
61+
`xorshift1024.RandomState` exposes a number of methods for generating random
62+
numbers drawn from a variety of probability distributions. In addition to the
63+
distribution-specific arguments, each method takes a keyword argument
64+
`size` that defaults to ``None``. If `size` is ``None``, then a single
65+
value is generated and returned. If `size` is an integer, then a 1-D
66+
array filled with generated values is returned. If `size` is a tuple,
67+
then an array with that shape is filled and returned.
68+
69+
*No Compatibility Guarantee*
70+
'xorshift1024.RandomState' does not make a guarantee that a fixed seed and a
71+
fixed series of calls to 'xorshift1024.RandomState' methods using the same
72+
parameters will always produce the same results. This is different from
73+
'numpy.random.RandomState' guarantee. This is done to simplify improving
74+
random number generators. To ensure identical results, you must use the
75+
same release version.
76+
77+
Parameters
78+
----------
79+
seed : {None, int}, optional
80+
Random seed initializing the pseudo-random number generator.
81+
Can be an integer or ``None`` (the default).
82+
If `seed` is ``None``, then `xorshift1024.RandomState` will try to read data
83+
from ``/dev/urandom`` (or the Windows analogue) if available or seed from
84+
the clock otherwise.
85+
86+
Notes
87+
-----
88+
See xorshift128 for a faster implementation that has a smaller period.
89+
90+
References
91+
----------
92+
.. [1] "xorshift*/xorshift+ generators and the PRNG shootout",
93+
http://xorshift.di.unimi.it/
5294
"""

randomstate/shims/xorshift128/xorshift128-defs.pxi

Lines changed: 0 additions & 11 deletions
This file was deleted.

randomstate/shims/xorshift128/xorshift128.pxd

Lines changed: 0 additions & 39 deletions
This file was deleted.

randomstate/shims/xorshift128/xorshift128.pxi

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ RandomState(seed=None)
4949
Container for the xorshift128+ pseudo random number generator.
5050
5151
xorshift128+ is a 64-bit implementation of Saito and Matsumoto's XSadd
52-
generator. xorshift128+ has a period of 2**128 _ 1 and supports jumping the
53-
sequence in increments of 2**64, which allow multiple non-overlapping
52+
generator [1]_. xorshift128+ has a period of 2**128 - 1 and supports jumping
53+
the sequence in increments of 2**64, which allow multiple non-overlapping
5454
sequences to be generated.
5555
5656
`xorshift128.RandomState` exposes a number of methods for generating random
@@ -80,5 +80,11 @@ seed : {None, int}, optional
8080
8181
Notes
8282
-----
83-
See xorshift1024 for an implementation with a larger period and jump size.
83+
See xorshift1024 for an implementation with a larger period
84+
(2**1024 - 1) and jump size.
85+
86+
References
87+
----------
88+
.. [1] "xorshift*/xorshift+ generators and the PRNG shootout",
89+
http://xorshift.di.unimi.it/
8490
"""

0 commit comments

Comments
 (0)