summaryrefslogtreecommitdiff
path: root/doc/source/reference/random
diff options
context:
space:
mode:
Diffstat (limited to 'doc/source/reference/random')
-rw-r--r--doc/source/reference/random/brng/dsfmt.rst43
-rw-r--r--doc/source/reference/random/brng/index.rst42
-rw-r--r--doc/source/reference/random/brng/mt19937.rst42
-rw-r--r--doc/source/reference/random/brng/pcg32.rst43
-rw-r--r--doc/source/reference/random/brng/pcg64.rst43
-rw-r--r--doc/source/reference/random/brng/philox.rst43
-rw-r--r--doc/source/reference/random/brng/threefry.rst43
-rw-r--r--doc/source/reference/random/brng/threefry32.rst43
-rw-r--r--doc/source/reference/random/brng/xoroshiro128.rst42
-rw-r--r--doc/source/reference/random/brng/xorshift1024.rst42
-rw-r--r--doc/source/reference/random/brng/xoshiro256starstar.rst42
-rw-r--r--doc/source/reference/random/brng/xoshiro512starstar.rst42
-rw-r--r--doc/source/reference/random/change-log.rst39
-rw-r--r--doc/source/reference/random/entropy.rst6
-rw-r--r--doc/source/reference/random/extending.rst167
-rw-r--r--doc/source/reference/random/generator.rst85
-rw-r--r--doc/source/reference/random/index.rst221
-rw-r--r--doc/source/reference/random/legacy.rst110
-rw-r--r--doc/source/reference/random/multithreading.rst106
-rw-r--r--doc/source/reference/random/new-or-different.rst101
-rw-r--r--doc/source/reference/random/parallel.rst143
-rw-r--r--doc/source/reference/random/performance.py74
-rw-r--r--doc/source/reference/random/performance.rst77
-rw-r--r--doc/source/reference/random/references.rst5
24 files changed, 1644 insertions, 0 deletions
diff --git a/doc/source/reference/random/brng/dsfmt.rst b/doc/source/reference/random/brng/dsfmt.rst
new file mode 100644
index 000000000..a47586a50
--- /dev/null
+++ b/doc/source/reference/random/brng/dsfmt.rst
@@ -0,0 +1,43 @@
+Double SIMD Mersenne Twister (dSFMT)
+------------------------------------
+
+.. module:: numpy.random.dsfmt
+
+.. currentmodule:: numpy.random.dsfmt
+
+
+.. autoclass:: DSFMT
+ :exclude-members:
+
+Seeding and State
+=================
+
+.. autosummary::
+ :toctree: generated/
+
+ ~DSFMT.seed
+ ~DSFMT.state
+
+Parallel generation
+===================
+.. autosummary::
+ :toctree: generated/
+
+ ~DSFMT.jump
+
+Random Generator
+================
+.. autosummary::
+ :toctree: generated/
+
+ ~DSFMT.generator
+
+Extending
+=========
+.. autosummary::
+ :toctree: generated/
+
+ ~DSFMT.cffi
+ ~DSFMT.ctypes
+
+
diff --git a/doc/source/reference/random/brng/index.rst b/doc/source/reference/random/brng/index.rst
new file mode 100644
index 000000000..5241f9856
--- /dev/null
+++ b/doc/source/reference/random/brng/index.rst
@@ -0,0 +1,42 @@
+Basic Random Number Generators
+------------------------------
+
+.. currentmodule:: numpy.random
+
+The random values produced by :class:`~RandomGenerator`
+are produced by a basic RNG. These basic RNGs do not directly provide
+random numbers and only contains methods used for seeding, getting or
+setting the state, jumping or advancing the state, and for accessing
+low-level wrappers for consumption by code that can efficiently
+access the functions provided, e.g., `numba <https://numba.pydata.org>`_.
+
+Stable RNGs
+===========
+These RNGs will be included in future releases.
+
+
+.. toctree::
+ :maxdepth: 1
+
+ DSFMT <dsfmt>
+ MT19937 <mt19937>
+ PCG64 <pcg64>
+ Philox <philox>
+ ThreeFry <threefry>
+ XoroShiro128+ <xoroshiro128>
+ Xorshift1024*φ <xorshift1024>
+ Xoshiro256** <xoshiro256starstar>
+ Xoshiro512** <xoshiro512starstar>
+
+
+Experimental RNGs
+=================
+
+These RNGs are currently included for testing but are may not be
+permanent.
+
+.. toctree::
+ :maxdepth: 1
+
+ PCG32 <pcg32>
+ ThreeFry32 <threefry32>
diff --git a/doc/source/reference/random/brng/mt19937.rst b/doc/source/reference/random/brng/mt19937.rst
new file mode 100644
index 000000000..1bd3597c8
--- /dev/null
+++ b/doc/source/reference/random/brng/mt19937.rst
@@ -0,0 +1,42 @@
+Mersenne Twister (MT19937)
+--------------------------
+
+.. module:: numpy.random.mt19937
+
+.. currentmodule:: numpy.random.mt19937
+
+.. autoclass:: MT19937
+ :exclude-members:
+
+Seeding and State
+=================
+
+.. autosummary::
+ :toctree: generated/
+
+ ~MT19937.seed
+ ~MT19937.state
+
+Parallel generation
+===================
+.. autosummary::
+ :toctree: generated/
+
+ ~MT19937.jump
+
+Random Generator
+================
+.. autosummary::
+ :toctree: generated/
+
+ ~MT19937.generator
+
+Extending
+=========
+.. autosummary::
+ :toctree: generated/
+
+ ~MT19937.cffi
+ ~MT19937.ctypes
+
+
diff --git a/doc/source/reference/random/brng/pcg32.rst b/doc/source/reference/random/brng/pcg32.rst
new file mode 100644
index 000000000..f079f5a8c
--- /dev/null
+++ b/doc/source/reference/random/brng/pcg32.rst
@@ -0,0 +1,43 @@
+Parallel Congruent Generator (32-bit, PCG32)
+--------------------------------------------
+
+.. module:: numpy.random.pcg32
+
+.. currentmodule:: numpy.random.pcg32
+
+.. autoclass:: PCG32
+ :exclude-members:
+
+Seeding and State
+=================
+
+.. autosummary::
+ :toctree: generated/
+
+ ~PCG32.seed
+ ~PCG32.state
+
+Parallel generation
+===================
+.. autosummary::
+ :toctree: generated/
+
+ ~PCG32.advance
+ ~PCG32.jump
+
+Random Generator
+================
+.. autosummary::
+ :toctree: generated/
+
+ ~PCG32.generator
+
+Extending
+=========
+.. autosummary::
+ :toctree: generated/
+
+ ~PCG32.cffi
+ ~PCG32.ctypes
+
+
diff --git a/doc/source/reference/random/brng/pcg64.rst b/doc/source/reference/random/brng/pcg64.rst
new file mode 100644
index 000000000..93f026fcb
--- /dev/null
+++ b/doc/source/reference/random/brng/pcg64.rst
@@ -0,0 +1,43 @@
+Parallel Congruent Generator (64-bit, PCG64)
+--------------------------------------------
+
+.. module:: numpy.random.pcg64
+
+.. currentmodule:: numpy.random.pcg64
+
+.. autoclass:: PCG64
+ :exclude-members:
+
+Seeding and State
+=================
+
+.. autosummary::
+ :toctree: generated/
+
+ ~PCG64.seed
+ ~PCG64.state
+
+Parallel generation
+===================
+.. autosummary::
+ :toctree: generated/
+
+ ~PCG64.advance
+ ~PCG64.jump
+
+Random Generator
+================
+.. autosummary::
+ :toctree: generated/
+
+ ~PCG64.generator
+
+Extending
+=========
+.. autosummary::
+ :toctree: generated/
+
+ ~PCG64.cffi
+ ~PCG64.ctypes
+
+
diff --git a/doc/source/reference/random/brng/philox.rst b/doc/source/reference/random/brng/philox.rst
new file mode 100644
index 000000000..c1e047c54
--- /dev/null
+++ b/doc/source/reference/random/brng/philox.rst
@@ -0,0 +1,43 @@
+Philox Counter-based RNG
+------------------------
+
+.. module:: numpy.random.philox
+
+.. currentmodule:: numpy.random.philox
+
+.. autoclass:: Philox
+ :exclude-members:
+
+Seeding and State
+=================
+
+.. autosummary::
+ :toctree: generated/
+
+ ~Philox.seed
+ ~Philox.state
+
+Parallel generation
+===================
+.. autosummary::
+ :toctree: generated/
+
+ ~Philox.advance
+ ~Philox.jump
+
+Random Generator
+================
+.. autosummary::
+ :toctree: generated/
+
+ ~Philox.generator
+
+Extending
+=========
+.. autosummary::
+ :toctree: generated/
+
+ ~Philox.cffi
+ ~Philox.ctypes
+
+
diff --git a/doc/source/reference/random/brng/threefry.rst b/doc/source/reference/random/brng/threefry.rst
new file mode 100644
index 000000000..eefe16ea0
--- /dev/null
+++ b/doc/source/reference/random/brng/threefry.rst
@@ -0,0 +1,43 @@
+ThreeFry Counter-based RNG
+--------------------------
+
+.. module:: numpy.random.threefry
+
+.. currentmodule:: numpy.random.threefry
+
+.. autoclass:: ThreeFry
+ :exclude-members:
+
+Seeding and State
+=================
+
+.. autosummary::
+ :toctree: generated/
+
+ ~ThreeFry.seed
+ ~ThreeFry.state
+
+Parallel generation
+===================
+.. autosummary::
+ :toctree: generated/
+
+ ~ThreeFry.advance
+ ~ThreeFry.jump
+
+Random Generator
+================
+.. autosummary::
+ :toctree: generated/
+
+ ~ThreeFry.generator
+
+Extending
+=========
+.. autosummary::
+ :toctree: generated/
+
+ ~ThreeFry.cffi
+ ~ThreeFry.ctypes
+
+
diff --git a/doc/source/reference/random/brng/threefry32.rst b/doc/source/reference/random/brng/threefry32.rst
new file mode 100644
index 000000000..f0d3dc281
--- /dev/null
+++ b/doc/source/reference/random/brng/threefry32.rst
@@ -0,0 +1,43 @@
+ThreeFry32 Counter-based RNG
+----------------------------
+
+.. module:: numpy.random.threefry32
+
+.. currentmodule:: numpy.random.threefry32
+
+.. autoclass:: ThreeFry32
+ :exclude-members:
+
+Seeding and State
+=================
+
+.. autosummary::
+ :toctree: generated/
+
+ ~ThreeFry32.seed
+ ~ThreeFry32.state
+
+Parallel generation
+===================
+.. autosummary::
+ :toctree: generated/
+
+ ~ThreeFry32.advance
+ ~ThreeFry32.jump
+
+Random Generator
+================
+.. autosummary::
+ :toctree: generated/
+
+ ~ThreeFry32.generator
+
+Extending
+=========
+.. autosummary::
+ :toctree: generated/
+
+ ~ThreeFry32.cffi
+ ~ThreeFry32.ctypes
+
+
diff --git a/doc/source/reference/random/brng/xoroshiro128.rst b/doc/source/reference/random/brng/xoroshiro128.rst
new file mode 100644
index 000000000..590552236
--- /dev/null
+++ b/doc/source/reference/random/brng/xoroshiro128.rst
@@ -0,0 +1,42 @@
+Xoroshiro128+
+-------------
+
+.. module:: numpy.random.xoroshiro128
+
+.. currentmodule:: numpy.random.xoroshiro128
+
+.. autoclass:: Xoroshiro128
+ :exclude-members:
+
+Seeding and State
+=================
+
+.. autosummary::
+ :toctree: generated/
+
+ ~Xoroshiro128.seed
+ ~Xoroshiro128.state
+
+Parallel generation
+===================
+.. autosummary::
+ :toctree: generated/
+
+ ~Xoroshiro128.jump
+
+Random Generator
+================
+.. autosummary::
+ :toctree: generated/
+
+ ~Xoroshiro128.generator
+
+Extending
+=========
+.. autosummary::
+ :toctree: generated/
+
+ ~Xoroshiro128.cffi
+ ~Xoroshiro128.ctypes
+
+
diff --git a/doc/source/reference/random/brng/xorshift1024.rst b/doc/source/reference/random/brng/xorshift1024.rst
new file mode 100644
index 000000000..24ed3df04
--- /dev/null
+++ b/doc/source/reference/random/brng/xorshift1024.rst
@@ -0,0 +1,42 @@
+Xorshift1024*φ
+--------------
+
+.. module:: numpy.random.xorshift1024
+
+.. currentmodule:: numpy.random.xorshift1024
+
+.. autoclass:: Xorshift1024
+ :exclude-members:
+
+Seeding and State
+=================
+
+.. autosummary::
+ :toctree: generated/
+
+ ~Xorshift1024.seed
+ ~Xorshift1024.state
+
+Parallel generation
+===================
+.. autosummary::
+ :toctree: generated/
+
+ ~Xorshift1024.jump
+
+Random Generator
+================
+.. autosummary::
+ :toctree: generated/
+
+ ~Xorshift1024.generator
+
+Extending
+=========
+.. autosummary::
+ :toctree: generated/
+
+ ~Xorshift1024.cffi
+ ~Xorshift1024.ctypes
+
+
diff --git a/doc/source/reference/random/brng/xoshiro256starstar.rst b/doc/source/reference/random/brng/xoshiro256starstar.rst
new file mode 100644
index 000000000..85c445666
--- /dev/null
+++ b/doc/source/reference/random/brng/xoshiro256starstar.rst
@@ -0,0 +1,42 @@
+Xoshiro256**
+------------
+
+.. module:: numpy.random.xoshiro256starstar
+
+.. currentmodule:: numpy.random.xoshiro256starstar
+
+.. autoclass:: Xoshiro256StarStar
+ :exclude-members:
+
+Seeding and State
+=================
+
+.. autosummary::
+ :toctree: generated/
+
+ ~Xoshiro256StarStar.seed
+ ~Xoshiro256StarStar.state
+
+Parallel generation
+===================
+.. autosummary::
+ :toctree: generated/
+
+ ~Xoshiro256StarStar.jump
+
+Random Generator
+================
+.. autosummary::
+ :toctree: generated/
+
+ ~Xoshiro256StarStar.generator
+
+Extending
+=========
+.. autosummary::
+ :toctree: generated/
+
+ ~Xoshiro256StarStar.cffi
+ ~Xoshiro256StarStar.ctypes
+
+
diff --git a/doc/source/reference/random/brng/xoshiro512starstar.rst b/doc/source/reference/random/brng/xoshiro512starstar.rst
new file mode 100644
index 000000000..0c008d56e
--- /dev/null
+++ b/doc/source/reference/random/brng/xoshiro512starstar.rst
@@ -0,0 +1,42 @@
+Xoshiro512**
+------------
+
+.. module:: numpy.random.xoshiro512starstar
+
+.. currentmodule:: numpy.random.xoshiro512starstar
+
+.. autoclass:: Xoshiro512StarStar
+ :exclude-members:
+
+Seeding and State
+=================
+
+.. autosummary::
+ :toctree: generated/
+
+ ~Xoshiro512StarStar.seed
+ ~Xoshiro512StarStar.state
+
+Parallel generation
+===================
+.. autosummary::
+ :toctree: generated/
+
+ ~Xoshiro512StarStar.jump
+
+Random Generator
+================
+.. autosummary::
+ :toctree: generated/
+
+ ~Xoshiro512StarStar.generator
+
+Extending
+=========
+.. autosummary::
+ :toctree: generated/
+
+ ~Xoshiro512StarStar.cffi
+ ~Xoshiro512StarStar.ctypes
+
+
diff --git a/doc/source/reference/random/change-log.rst b/doc/source/reference/random/change-log.rst
new file mode 100644
index 000000000..af3c266ef
--- /dev/null
+++ b/doc/source/reference/random/change-log.rst
@@ -0,0 +1,39 @@
+Change Log for the original bashtage/randomgen repo
+---------------------------------------------------
+v1.16.1
+=======
+- Synchronized with upstream changes.
+- Fixed a bug in gamma generation if the shape parameters is 0.0.
+
+v1.16.0
+=======
+- Fixed a bug that affected ``randomgen.dsfmt.DSFMT`` when calling
+ ``~randomgen.dsfmt.DSFMT.jump`` or ``randomgen.dsfmt.DSFMT.seed``
+ that failed to reset the buffer. This resulted in upto 381 values from the
+ previous state being used before the buffer was refilled at the new state.
+- Fixed bugs in ``randomgen.xoshiro512starstar.Xoshiro512StarStar``
+ and ``randomgen.xorshift1024.Xorshift1024`` where the fallback
+ entropy initialization used too few bytes. This bug is unlikely to be
+ encountered since this path is only encountered if the system random
+ number generator fails.
+- Synchronized with upstream changes.
+
+v1.15.1
+=======
+- Added Xoshiro256** and Xoshiro512**, the preferred generators of this class.
+- Fixed bug in `jump` method of Random123 generators which did nto specify a default value.
+- Added support for generating bounded uniform integers using Lemire's method.
+- Synchronized with upstream changes, which requires moving the minimum supported NumPy to 1.13.
+
+v1.15
+=====
+- Synced empty choice changes
+- Synced upstream docstring changes
+- Synced upstream changes in permutation
+- Synced upstream doc fixes
+- Added absolute_import to avoid import noise on Python 2.7
+- Add legacy generator which allows NumPy replication
+- Improve type handling of integers
+- Switch to array-fillers for 0 parameter distribution to improve performance
+- Small changes to build on manylinux
+- Build wheels using multibuild
diff --git a/doc/source/reference/random/entropy.rst b/doc/source/reference/random/entropy.rst
new file mode 100644
index 000000000..0664da6f9
--- /dev/null
+++ b/doc/source/reference/random/entropy.rst
@@ -0,0 +1,6 @@
+System Entropy
+==============
+
+.. module:: numpy.random.entropy
+
+.. autofunction:: random_entropy
diff --git a/doc/source/reference/random/extending.rst b/doc/source/reference/random/extending.rst
new file mode 100644
index 000000000..f76e3984f
--- /dev/null
+++ b/doc/source/reference/random/extending.rst
@@ -0,0 +1,167 @@
+.. currentmodule:: numpy.random
+
+Extending
+---------
+The basic RNGs have been designed to be extendable using standard tools for
+high-performance Python -- numba and Cython.
+The `~RandomGenerator` object can also be used with
+user-provided basic RNGs as long as these export a small set of required
+functions.
+
+Numba
+=====
+Numba can be used with either CTypes or CFFI. The current iteration of the
+basic RNGs all export a small set of functions through both interfaces.
+
+This example shows how numba can be used to produce Box-Muller normals using
+a pure Python implementation which is then compiled. The random numbers are
+provided by ``ctypes.next_double``.
+
+.. code-block:: python
+
+ from numpy.random import Xoroshiro128
+ import numpy as np
+ import numba as nb
+
+ x = Xoroshiro128()
+ f = x.ctypes.next_double
+ s = x.ctypes.state
+ state_addr = x.ctypes.state_address
+
+ def normals(n, state):
+ out = np.empty(n)
+ for i in range((n+1)//2):
+ x1 = 2.0*f(state) - 1.0
+ x2 = 2.0*f(state) - 1.0
+ r2 = x1*x1 + x2*x2
+ while r2 >= 1.0 or r2 == 0.0:
+ x1 = 2.0*f(state) - 1.0
+ x2 = 2.0*f(state) - 1.0
+ r2 = x1*x1 + x2*x2
+ g = np.sqrt(-2.0*np.log(r2)/r2)
+ out[2*i] = g*x1
+ if 2*i+1 < n:
+ out[2*i+1] = g*x2
+ return out
+
+ # Compile using Numba
+ print(normals(10, s).var())
+ # Warm up
+ normalsj = nb.jit(normals, nopython=True)
+ # Must use state address not state with numba
+ normalsj(1, state_addr)
+ %timeit normalsj(1000000, state_addr)
+ print('1,000,000 Box-Muller (numba/Xoroshiro128) randoms')
+ %timeit np.random.standard_normal(1000000)
+ print('1,000,000 Box-Muller (NumPy) randoms')
+
+
+Both CTypes and CFFI allow the more complicated distributions to be used
+directly in Numba after compiling the file distributions.c into a DLL or so.
+An example showing the use of a more complicated distribution is in the
+examples folder.
+
+.. _randomgen_cython:
+
+Cython
+======
+
+Cython can be used to unpack the ``PyCapsule`` provided by a basic RNG.
+This example uses `~xoroshiro128.Xoroshiro128` and
+``random_gauss_zig``, the Ziggurat-based generator for normals, to fill an
+array. The usual caveats for writing high-performance code using Cython --
+removing bounds checks and wrap around, providing array alignment information
+-- still apply.
+
+.. code-block:: cython
+
+ import numpy as np
+ cimport numpy as np
+ cimport cython
+ from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer
+ from numpy.random.common cimport *
+ from numpy.random.distributions cimport random_gauss_zig
+ from numpy.random.xoroshiro128 import Xoroshiro128
+
+
+ @cython.boundscheck(False)
+ @cython.wraparound(False)
+ def normals_zig(Py_ssize_t n):
+ cdef Py_ssize_t i
+ cdef brng_t *rng
+ cdef const char *capsule_name = "BasicRNG"
+ cdef double[::1] random_values
+
+ x = Xoroshiro128()
+ capsule = x.capsule
+ # Optional check that the capsule if from a Basic RNG
+ if not PyCapsule_IsValid(capsule, capsule_name):
+ raise ValueError("Invalid pointer to anon_func_state")
+ # Cast the pointer
+ rng = <brng_t *> PyCapsule_GetPointer(capsule, capsule_name)
+ random_values = np.empty(n)
+ for i in range(n):
+ # Call the function
+ random_values[i] = random_gauss_zig(rng)
+ randoms = np.asarray(random_values)
+ return randoms
+
+
+The basic RNG can also be directly accessed using the members of the basic
+RNG structure.
+
+.. code-block:: cython
+
+ @cython.boundscheck(False)
+ @cython.wraparound(False)
+ def uniforms(Py_ssize_t n):
+ cdef Py_ssize_t i
+ cdef brng_t *rng
+ cdef const char *capsule_name = "BasicRNG"
+ cdef double[::1] random_values
+
+ x = Xoroshiro128()
+ capsule = x.capsule
+ # Optional check that the capsule if from a Basic RNG
+ if not PyCapsule_IsValid(capsule, capsule_name):
+ raise ValueError("Invalid pointer to anon_func_state")
+ # Cast the pointer
+ rng = <brng_t *> PyCapsule_GetPointer(capsule, capsule_name)
+ random_values = np.empty(n)
+ for i in range(n):
+ # Call the function
+ random_values[i] = rng.next_double(rng.state)
+ randoms = np.asarray(random_values)
+ return randoms
+
+These functions along with a minimal setup file are included in the
+examples folder.
+
+New Basic RNGs
+==============
+`~RandomGenerator` can be used with other
+user-provided basic RNGs. The simplest way to write a new basic RNG is to
+examine the pyx file of one of the existing basic RNGs. The key structure
+that must be provided is the ``capsule`` which contains a ``PyCapsule`` to a
+struct pointer of type ``brng_t``,
+
+.. code-block:: c
+
+ typedef struct brng {
+ void *state;
+ uint64_t (*next_uint64)(void *st);
+ uint32_t (*next_uint32)(void *st);
+ double (*next_double)(void *st);
+ uint64_t (*next_raw)(void *st);
+ } brng_t;
+
+which provides 5 pointers. The first is an opaque pointer to the data structure
+used by the basic RNG. The next three are function pointers which return the
+next 64- and 32-bit unsigned integers, the next random double and the next
+raw value. This final function is used for testing and so can be set to
+the next 64-bit unsigned integer function if not needed. Functions inside
+``RandomGenerator`` use this structure as in
+
+.. code-block:: c
+
+ brng_state->next_uint64(brng_state->state)
diff --git a/doc/source/reference/random/generator.rst b/doc/source/reference/random/generator.rst
new file mode 100644
index 000000000..9d248732f
--- /dev/null
+++ b/doc/source/reference/random/generator.rst
@@ -0,0 +1,85 @@
+.. currentmodule:: numpy.random
+
+Random Generator
+----------------
+The `~RandomGenerator` provides access to
+a wide range of distributions, and served as a replacement for
+:class:`~numpy.random.RandomState`. The main difference between
+the two is that ``RandomGenerator`` relies on an additional basic RNG to
+manage state and generate the random bits, which are then transformed into
+random values from useful distributions. The default basic RNG used by
+``RandomGenerator`` is :class:`~xoroshiro128.Xoroshiro128`. The basic RNG can be
+changed by passing an instantized basic RNG to ``RandomGenerator``.
+
+
+.. autoclass:: RandomGenerator
+ :exclude-members:
+
+Accessing the RNG
+=================
+.. autosummary::
+ :toctree: generated/
+
+ ~RandomGenerator.brng
+
+Simple random data
+==================
+.. autosummary::
+ :toctree: generated/
+
+ ~RandomGenerator.rand
+ ~RandomGenerator.randn
+ ~RandomGenerator.randint
+ ~RandomGenerator.random_integers
+ ~RandomGenerator.random_sample
+ ~RandomGenerator.choice
+ ~RandomGenerator.bytes
+
+Permutations
+============
+.. autosummary::
+ :toctree: generated/
+
+ ~RandomGenerator.shuffle
+ ~RandomGenerator.permutation
+
+Distributions
+=============
+.. autosummary::
+ :toctree: generated/
+
+ ~RandomGenerator.beta
+ ~RandomGenerator.binomial
+ ~RandomGenerator.chisquare
+ ~RandomGenerator.dirichlet
+ ~RandomGenerator.exponential
+ ~RandomGenerator.f
+ ~RandomGenerator.gamma
+ ~RandomGenerator.geometric
+ ~RandomGenerator.gumbel
+ ~RandomGenerator.hypergeometric
+ ~RandomGenerator.laplace
+ ~RandomGenerator.logistic
+ ~RandomGenerator.lognormal
+ ~RandomGenerator.logseries
+ ~RandomGenerator.multinomial
+ ~RandomGenerator.multivariate_normal
+ ~RandomGenerator.negative_binomial
+ ~RandomGenerator.noncentral_chisquare
+ ~RandomGenerator.noncentral_f
+ ~RandomGenerator.normal
+ ~RandomGenerator.pareto
+ ~RandomGenerator.poisson
+ ~RandomGenerator.power
+ ~RandomGenerator.rayleigh
+ ~RandomGenerator.standard_cauchy
+ ~RandomGenerator.standard_exponential
+ ~RandomGenerator.standard_gamma
+ ~RandomGenerator.standard_normal
+ ~RandomGenerator.standard_t
+ ~RandomGenerator.triangular
+ ~RandomGenerator.uniform
+ ~RandomGenerator.vonmises
+ ~RandomGenerator.wald
+ ~RandomGenerator.weibull
+ ~RandomGenerator.zipf
diff --git a/doc/source/reference/random/index.rst b/doc/source/reference/random/index.rst
new file mode 100644
index 000000000..1cbf5c685
--- /dev/null
+++ b/doc/source/reference/random/index.rst
@@ -0,0 +1,221 @@
+.. currentmodule:: numpy.random
+
+numpy.random
+============
+
+A `~RandomGenerator` can
+be initialized with a number of different Random Number Generators (RNG)s, and
+exposes many different probability distributions.
+
+
+Quick Start
+-----------
+
+By default, `RandomGenerator` uses normals provided by
+`xoroshiro128.Xoroshiro128` which will be faster than the legacy methods in
+`numpy.random.RandomState`
+
+.. code-block:: python
+
+ # As replacement for numpy.random.RandomState
+ from numpy import random
+ random.standard_normal()
+
+`RandomGenerator` can be used as a direct replacement for
+`~RandomState`, although the random values are generated by
+`~xoroshiro128.Xoroshiro128`. The `RandomGenerator` holds an instance of a RNG.
+It is accessable as ``gen.brng``.
+
+.. code-block:: python
+
+ # As replacement for RandomState()
+ from numpy.random import RandomGenerator
+ rg = RandomGenerator()
+ rg.standard_normal()
+
+
+Seeds can be passed to any of the basic RNGs. Here `mt19937.MT19937` is used
+and the ``RandomGenerator`` is accessed via the attribute `mt19937.MT19937.
+generator`.
+
+.. code-block:: python
+
+ from numpy.random import MT19937
+ rg = MT19937(12345).generator
+ rg.standard_normal()
+
+
+Introduction
+------------
+RandomGen takes a different approach to producing random numbers from the
+:class:`numpy.random.RandomState` object. Random number generation is
+separated into two components, a basic RNG and a random generator.
+
+The basic RNG has a limited set of responsibilities. It manages the
+underlying RNG state and provides functions to produce random doubles and
+random unsigned 32- and 64-bit values. The basic random generator also handles
+all seeding since this varies when using alternative basic RNGs.
+
+The `random generator <~RandomGenerator>` takes the
+basic RNG-provided functions and transforms them into more useful
+distributions, e.g., simulated normal random values. This structure allows
+alternative basic RNGs to be used without code duplication.
+
+The ``RandomGenerator`` is the user-facing object
+that is nearly identical to :class:`~.RandomState`. The canonical
+method to initialize a generator passes a basic RNG -- `~mt19937.MT19937`, the
+underlying RNG in NumPy -- as the sole argument. Note that the basic RNG must
+be instantized.
+
+.. code-block:: python
+
+ from numpy.random import RandomGenerator, MT19937
+ rg = RandomGenerator(MT19937())
+ rg.random_sample()
+
+Seed information is directly passed to the basic RNG.
+
+.. code-block:: python
+
+ rg = RandomGenerator(MT19937(12345))
+ rg.random_sample()
+
+A shorthand method is also available which uses the `~mt19937.MT19937.
+generator` property from a basic RNG to access an embedded random generator.
+
+.. code-block:: python
+
+ rg = MT19937(12345).generator
+ rg.random_sample()
+
+What's New or Different
+~~~~~~~~~~~~~~~~~~~~~~~
+.. warning::
+
+ The Box-Muller method used to produce NumPy's normals is no longer available
+ in `~RandomGenerator`. It is not possible to reproduce the random values
+ using ``RandomGenerator`` for the normal distribution or any other
+ distribution that relies on the normal such as the gamma or student's t.
+ If you require backward compatibility, a legacy generator, `~legacy.
+ LegacyGenerator`, has been created which can fully reproduce the sequence
+ produced by NumPy.
+
+* The normal, exponential and gamma generators use 256-step Ziggurat
+ methods which are 2-10 times faster than NumPy's Box-Muller or inverse CDF
+ implementations.
+* Optional ``dtype`` argument that accepts ``np.float32`` or ``np.float64``
+ to produce either single or double prevision uniform random variables for
+ select distributions
+* Optional ``out`` argument that allows existing arrays to be filled for
+ select distributions
+* `~entropy.random_entropy` provides access to the system
+ source of randomness that is used in cryptographic applications (e.g.,
+ ``/dev/urandom`` on Unix).
+* All basic random generators functions can produce doubles, uint64s and
+ uint32s via CTypes (`~xoroshiro128.Xoroshiro128.ctypes`)
+ and CFFI (:meth:`~xoroshiro128.Xoroshiro128.cffi`).
+ This allows these basic RNGs to be used in numba.
+* The basic random number generators can be used in downstream projects via
+ :ref:`Cython <randomgen_cython>`.
+* Support for Lemire’s method [Lemire]_ of generating uniform integers on an
+ arbitrary interval by setting ``use_masked=True`` in
+ `~RandomGenerator.randint`.
+
+
+See :ref:`new-or-different` for a complete list of improvements and
+differences.
+
+Parallel Generation
+~~~~~~~~~~~~~~~~~~~
+
+The included generators can be used in parallel, distributed applications in
+one of two ways:
+
+* :ref:`independent-streams`
+* :ref:`jump-and-advance`
+
+Supported Generators
+--------------------
+The main innovation is the inclusion of a number of alternative pseudo-random number
+generators, 'in addition' to the standard PRNG in NumPy. The included PRNGs are:
+
+* MT19937 - The standard NumPy generator. Produces identical results to NumPy
+ using the same seed/state. Adds a
+ `~mt19937.MT19937.jump` function that advances the
+ generator as-if ``2**128`` draws have been made. See `numpy.random`.
+* dSFMT - SSE2 enabled versions of the MT19937 generator. Theoretically
+ the same, but with a different state and so it is not possible to produce a
+ sequence identical to MT19937. Supports ``jump`` and so can
+ be used in parallel applications. See the `dSFMT authors' page`_.
+* XoroShiro128+ - Improved version of XorShift128+ with better performance
+ and statistical quality. Like the XorShift generators, it can be jumped
+ to produce multiple streams in parallel applications. See
+ `~xoroshiro128.Xoroshiro128.jump` for details.
+ More information about this PRNG is available at the
+ `xorshift, xoroshiro and xoshiro authors' page`_.
+* XorShift1024*φ - Fast fast generator based on the XSadd
+ generator. Supports ``jump`` and so can be used in
+ parallel applications. See the documentation for
+ `~xorshift1024.Xorshift1024.jump` for details. More
+ information about these PRNGs is available at the
+ `xorshift, xoroshiro and xoshiro authors' page`_.
+* Xorshiro256** and Xorshiro512** - The most recently introduced XOR,
+ shift, and rotate generator. Supports ``jump`` and so can be used in
+ parallel applications. See the documentation for
+ `~xoshiro256starstar.Xoshirt256StarStar.jump` for
+ details. More information about these PRNGs is available at the
+ `xorshift, xoroshiro and xoshiro authors' page`_.
+* PCG-64 - Fast generator that support many parallel streams and
+ can be advanced by an arbitrary amount. See the documentation for
+ `~pcg64.PCG64.advance`. PCG-64 has a period of
+ :math:`2^{128}`. See the `PCG author's page`_ for more details about
+ this class of PRNG.
+* ThreeFry and Philox - counter-based generators capable of being advanced an
+ arbitrary number of steps or generating independent streams. See the
+ `Random123`_ page for more details about this class of PRNG.
+
+.. _`dSFMT authors' page`: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/
+.. _`xorshift, xoroshiro and xoshiro authors' page`: http://xoroshiro.di.unimi.it/
+.. _`PCG author's page`: http://www.pcg-random.org/
+.. _`Random123`: https://www.deshawresearch.com/resources_random123.html
+
+Random Generator
+----------------
+.. toctree::
+ :maxdepth: 1
+
+ generator
+ legacy
+
+Basic Random Number Generators
+------------------------------
+
+.. toctree::
+ :maxdepth: 1
+
+ Basic Random Number Generators <brng/index>
+
+New Features
+------------
+.. toctree::
+ :maxdepth: 2
+
+ Parallel Applications <parallel>
+ Multithreaded Generation <multithreading>
+ new-or-different
+ Comparing Performance <performance>
+ extending
+ Reading System Entropy <entropy>
+ references
+
+Changes
+~~~~~~~
+
+This package was developed independently of NumPy and was integrated in version
+1.17.0. The original repo is at https://github.com/bashtage/randomgen.
+
+.. toctree::
+ :maxdepth: 2
+
+ Change Log <change-log>
+
diff --git a/doc/source/reference/random/legacy.rst b/doc/source/reference/random/legacy.rst
new file mode 100644
index 000000000..b9bfabcc7
--- /dev/null
+++ b/doc/source/reference/random/legacy.rst
@@ -0,0 +1,110 @@
+Legacy Random Generation
+------------------------
+The :class:`~legacy.LegacyGenerator` provides access to
+legacy generators. These all depend on Box-Muller normals or
+inverse CDF exponentials or gammas. This class should only be used
+if it is essential to have randoms that are identical to what
+would have been produced by NumPy.
+
+:class:`~legacy.LegacyGenerator` add additional information
+to the state which is required when using Box-Muller normals since these
+are produced in pairs. It is important to use
+:attr:`~legacy.LegacyGenerator.state`
+when accessing the state so that these extra values are saved.
+
+.. warning::
+
+ :class:`~randomgen.legacy.LegacyGenerator` only contains functions
+ that have changed. Since it does not contain other functions, it
+ is not direclty possible to replace :class:`~numpy.random.RandomState`.
+ In order to full replace :class:`~numpy.random.RandomState`, it is
+ necessary to use both :class:`~randomgen.legacy.LegacyGenerator`
+ and :class:`~randomgen.generator.RandomGenerator` both driven
+ by the same basic RNG. Methods present in :class:`~randomgen.legacy.LegacyGenerator`
+ must be called from :class:`~randomgen.legacy.LegacyGenerator`. Other Methods
+ should be called from :class:`~randomgen.generator.RandomGenerator`.
+
+
+.. code-block:: python
+
+ from numpy.random import MT19937
+ from numpy.random.legacy import LegacyGenerator
+ from numpy.random import RandomState
+ # Use same seed
+ rs = RandomState(12345)
+ mt19937 = MT19937(12345)
+ rg = RandomGenerator(mt19937)
+ lg = LegacyGenerator(mt19937)
+
+ # Identical output
+ rs.standard_normal()
+ lg.standard_normal()
+
+ rs.random_sample()
+ rg.random_sample()
+
+ rs.standard_exponential()
+ lg.standard_exponential()
+
+
+.. currentmodule:: numpy.random.legacy
+
+.. autoclass:: LegacyGenerator
+ :exclude-members:
+
+Seeding and State
+=================
+
+.. autosummary::
+ :toctree: generated/
+
+ ~LegacyGenerator.get_state
+ ~LegacyGenerator.set_state
+
+Simple random data
+==================
+.. autosummary::
+ :toctree: generated/
+
+ ~LegacyGenerator.randn
+ ~LegacyGenerator.randint
+ ~LegacyGenerator.random_integers
+ ~LegacyGenerator.random_sample
+ ~LegacyGenerator.choice
+ ~LegacyGenerator.bytes
+
+Permutations
+============
+.. autosummary::
+ :toctree: generated/
+
+ ~LegacyGenerator.shuffle
+ ~LegacyGenerator.permutation
+
+Distributions
+=============
+.. autosummary::
+ :toctree: generated/
+
+ ~LegacyGenerator.beta
+ ~LegacyGenerator.chisquare
+ ~LegacyGenerator.dirichlet
+ ~LegacyGenerator.exponential
+ ~LegacyGenerator.f
+ ~LegacyGenerator.gamma
+ ~LegacyGenerator.lognormal
+ ~LegacyGenerator.multivariate_normal
+ ~LegacyGenerator.negative_binomial
+ ~LegacyGenerator.noncentral_chisquare
+ ~LegacyGenerator.noncentral_f
+ ~LegacyGenerator.normal
+ ~LegacyGenerator.pareto
+ ~LegacyGenerator.power
+ ~LegacyGenerator.standard_cauchy
+ ~LegacyGenerator.standard_exponential
+ ~LegacyGenerator.standard_gamma
+ ~LegacyGenerator.standard_normal
+ ~LegacyGenerator.standard_t
+ ~LegacyGenerator.wald
+ ~LegacyGenerator.weibull
+ ~LegacyGenerator.zipf
diff --git a/doc/source/reference/random/multithreading.rst b/doc/source/reference/random/multithreading.rst
new file mode 100644
index 000000000..f7762b73a
--- /dev/null
+++ b/doc/source/reference/random/multithreading.rst
@@ -0,0 +1,106 @@
+Multithreaded Generation
+========================
+
+The four core distributions all allow existing arrays to be filled using the
+``out`` keyword argument. Existing arrays need to be contiguous and
+well-behaved (writable and aligned). Under normal circumstances, arrays
+created using the common constructors such as :meth:`numpy.empty` will satisfy
+these requirements.
+
+This example makes use of Python 3 :mod:`concurrent.futures` to fill an array
+using multiple threads. Threads are long-lived so that repeated calls do not
+require any additional overheads from thread creation. The underlying PRNG is
+xorshift2014 which is fast, has a long period and supports using ``jump`` to
+advance the state. The random numbers generated are reproducible in the sense
+that the same seed will produce the same outputs.
+
+.. code-block:: ipython
+
+ from numpy.random import Xorshift1024
+ import multiprocessing
+ import concurrent.futures
+ import numpy as np
+
+ class MultithreadedRNG(object):
+ def __init__(self, n, seed=None, threads=None):
+ rg = Xorshift1024(seed)
+ if threads is None:
+ threads = multiprocessing.cpu_count()
+ self.threads = threads
+
+ self._random_generators = []
+ for _ in range(0, threads-1):
+ _rg = Xorshift1024()
+ _rg.state = rg.state
+ self._random_generators.append(_rg.generator)
+ rg.jump()
+ self._random_generators.append(rg.generator)
+
+ self.n = n
+ self.executor = concurrent.futures.ThreadPoolExecutor(threads)
+ self.values = np.empty(n)
+ self.step = np.ceil(n / threads).astype(np.int)
+
+ def fill(self):
+ def _fill(random_state, out, first, last):
+ random_state.standard_normal(out=out[first:last])
+
+ futures = {}
+ for i in range(self.threads):
+ args = (_fill,
+ self._random_generators[i],
+ self.values,
+ i * self.step,
+ (i + 1) * self.step)
+ futures[self.executor.submit(*args)] = i
+ concurrent.futures.wait(futures)
+
+ def __del__(self):
+ self.executor.shutdown(False)
+
+
+The multithreaded random number generator can be used to fill an array.
+The ``values`` attributes shows the zero-value before the fill and the
+random value after.
+
+.. code-block:: ipython
+
+ In [2]: mrng = MultithreadedRNG(10000000, seed=0)
+ ...: print(mrng.values[-1])
+ 0.0
+
+ In [3]: mrng.fill()
+ ...: print(mrng.values[-1])
+ 3.296046120254392
+
+The time required to produce using multiple threads can be compared to
+the time required to generate using a single thread.
+
+.. code-block:: ipython
+
+ In [4]: print(mrng.threads)
+ ...: %timeit mrng.fill()
+
+ 4
+ 32.8 ms ± 2.71 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
+
+The single threaded call directly uses the PRNG.
+
+.. code-block:: ipython
+
+ In [5]: values = np.empty(10000000)
+ ...: rg = Xorshift1024().generator
+ ...: %timeit rg.standard_normal(out=values)
+
+ 99.6 ms ± 222 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
+
+The gains are substantial and the scaling is reasonable even for large that
+are only moderately large. The gains are even larger when compared to a call
+that does not use an existing array due to array creation overhead.
+
+.. code-block:: ipython
+
+ In [6]: rg = Xorshift1024().generator
+ ...: %timeit rg.standard_normal(10000000)
+
+ 125 ms ± 309 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
diff --git a/doc/source/reference/random/new-or-different.rst b/doc/source/reference/random/new-or-different.rst
new file mode 100644
index 000000000..7ddebb5b2
--- /dev/null
+++ b/doc/source/reference/random/new-or-different.rst
@@ -0,0 +1,101 @@
+.. _new-or-different:
+
+.. currentmodule:: numpy.random
+
+What's New or Different
+-----------------------
+
+.. warning::
+
+ The Box-Muller method used to produce NumPy's normals is no longer available
+ in `~.RandomGenerator`. It is not possible to
+ reproduce the exact random values using ``RandomGenerator`` for the normal
+ distribution or any other distribution that relies on the normal such as the
+ `numpy.random.gamma` or `numpy.random.standard_t`. If you require backward
+ compatibility, a legacy generator, `~.legacy.
+ LegacyGenerator`, has been created which can fully reproduce the exact byte
+ sequence produced by legacy code.
+
+
+* `~.entropy.random_entropy` provides access to the system
+ source of randomness that is used in cryptographic applications (e.g.,
+ ``/dev/urandom`` on Unix).
+* Simulate from the complex normal distribution
+ (`~.RandomGenerator.complex_normal`)
+* The normal, exponential and gamma generators use 256-step Ziggurat
+ methods which are 2-10 times faster than NumPy's default implementation in
+ `~.RandomGenerator.standard_normal`,
+ `~.RandomGenerator.standard_exponential` or
+ `~.RandomGenerator.standard_gamma`.
+* The Box-Muller used to produce NumPy's normals is no longer available.
+* All basic random generators functions to produce doubles, uint64s and
+ uint32s via CTypes (`~.xoroshiro128.Xoroshiro128.
+ ctypes`) and CFFI (`~.xoroshiro128.Xoroshiro128.cffi`).
+ This allows these basic RNGs to be used in numba.
+* The basic random number generators can be used in downstream projects via
+ Cython.
+
+
+.. ipython:: python
+
+ from numpy.random import Xoroshiro128
+ import numpy.random
+ rg = Xoroshiro128().generator
+ %timeit rg.standard_normal(100000)
+ %timeit numpy.random.standard_normal(100000)
+
+.. ipython:: python
+
+ %timeit rg.standard_exponential(100000)
+ %timeit numpy.random.standard_exponential(100000)
+
+.. ipython:: python
+
+ %timeit rg.standard_gamma(3.0, 100000)
+ %timeit numpy.random.standard_gamma(3.0, 100000)
+
+* Optional ``dtype`` argument that accepts ``np.float32`` or ``np.float64``
+ to produce either single or double prevision uniform random variables for
+ select distributions
+
+ * Uniforms (`~.RandomGenerator.random_sample` and
+ `~.RandomGenerator.rand`)
+ * Normals (`~.RandomGenerator.standard_normal` and
+ `~.RandomGenerator.randn`)
+ * Standard Gammas (`~.RandomGenerator.standard_gamma`)
+ * Standard Exponentials (`~.RandomGenerator.standard_exponential`)
+
+.. ipython:: python
+
+ rg.brng.seed(0)
+ rg.random_sample(3, dtype='d')
+ rg.brng.seed(0)
+ rg.random_sample(3, dtype='f')
+
+* Optional ``out`` argument that allows existing arrays to be filled for
+ select distributions
+
+ * Uniforms (`~.RandomGenerator.random_sample`)
+ * Normals (`~.RandomGenerator.standard_normal`)
+ * Standard Gammas (`~.RandomGenerator.standard_gamma`)
+ * Standard Exponentials (`~.RandomGenerator.standard_exponential`)
+
+ This allows multithreading to fill large arrays in chunks using suitable
+ PRNGs in parallel.
+
+.. ipython:: python
+
+ existing = np.zeros(4)
+ rg.random_sample(out=existing[:2])
+ print(existing)
+
+.. * For changes since the previous release, see the :ref:`change-log`
+
+* Support for Lemire’s method of generating uniform integers on an
+ arbitrary interval by setting ``use_masked=True`` in
+ (`~.RandomGenerator.randint`).
+
+.. ipython:: python
+
+ %timeit rg.randint(0, 1535, use_masked=False)
+ %timeit numpy.random.randint(0, 1535)
diff --git a/doc/source/reference/random/parallel.rst b/doc/source/reference/random/parallel.rst
new file mode 100644
index 000000000..41e47039d
--- /dev/null
+++ b/doc/source/reference/random/parallel.rst
@@ -0,0 +1,143 @@
+Parallel Random Number Generation
+=================================
+
+There are three strategies implemented that can be used to produce
+repeatable pseudo-random numbers across multiple processes (local
+or distributed).
+
+.. _independent-streams:
+
+.. currentmodule:: numpy.random
+
+Independent Streams
+-------------------
+
+:class:`~pcg64.PCG64`, :class:`~threefry.ThreeFry`
+and :class:`~philox.Philox` support independent streams. This
+example shows how many streams can be created by passing in different index
+values in the second input while using the same seed in the first.
+
+.. code-block:: python
+
+ from numpy.random.entropy import random_entropy
+ from numpy.random import PCG64
+
+ entropy = random_entropy(4)
+ # 128-bit number as a seed
+ seed = sum([int(entropy[i]) * 2 ** (32 * i) for i in range(4)])
+ streams = [PCG64(seed, stream) for stream in range(10)]
+
+
+:class:`~philox.Philox` and :class:`~threefry.ThreeFry` are
+counter-based RNGs which use a counter and key. Different keys can be used
+to produce independent streams.
+
+.. code-block:: python
+
+ import numpy as np
+ from numpy.random import ThreeFry
+
+ key = random_entropy(8)
+ key = key.view(np.uint64)
+ key[0] = 0
+ step = np.zeros(4, dtype=np.uint64)
+ step[0] = 1
+ streams = [ThreeFry(key=key + stream * step) for stream in range(10)]
+
+.. _jump-and-advance:
+
+Jump/Advance the PRNG state
+---------------------------
+
+Jump
+****
+
+``jump`` advances the state of the PRNG *as-if* a large number of random
+numbers have been drawn. The specific number of draws varies by PRNG, and
+ranges from :math:`2^{64}` to :math:`2^{512}`. Additionally, the *as-if*
+draws also depend on the size of the default random number produced by the
+specific PRNG. The PRNGs that support ``jump``, along with the period of
+the PRNG, the size of the jump and the bits in the default unsigned random
+are listed below.
+
++-----------------+-------------------------+-------------------------+-------------------------+
+| PRNG | Period | Jump Size | Bits |
++=================+=========================+=========================+=========================+
+| DSFMT | :math:`2^{19937}` | :math:`2^{128}` | 53 |
++-----------------+-------------------------+-------------------------+-------------------------+
+| MT19937 | :math:`2^{19937}` | :math:`2^{128}` | 32 |
++-----------------+-------------------------+-------------------------+-------------------------+
+| PCG64 | :math:`2^{128}` | :math:`2^{64}` | 64 |
++-----------------+-------------------------+-------------------------+-------------------------+
+| Philox | :math:`2^{256}` | :math:`2^{128}` | 64 |
++-----------------+-------------------------+-------------------------+-------------------------+
+| ThreeFry | :math:`2^{256}` | :math:`2^{128}` | 64 |
++-----------------+-------------------------+-------------------------+-------------------------+
+| Xoroshiro128 | :math:`2^{128}` | :math:`2^{64}` | 64 |
++-----------------+-------------------------+-------------------------+-------------------------+
+| Xorshift1024 | :math:`2^{1024}` | :math:`2^{512}` | 64 |
++-----------------+-------------------------+-------------------------+-------------------------+
+
+``jump`` can be used to produce long blocks which should be long enough to not
+overlap.
+
+.. code-block:: python
+
+ from numpy.random.entropy import random_entropy
+ from numpy.random import Xorshift1024
+
+ entropy = random_entropy(2).astype(np.uint64)
+ # 64-bit number as a seed
+ seed = entropy[0] * 2**32 + entropy[1]
+ blocked_rng = []
+ for i in range(10):
+ rng = Xorshift1024(seed)
+ rng.jump(i)
+ blocked_rng.append(rng)
+
+
+Advance
+*******
+``advance`` can be used to jump the state an arbitrary number of steps, and so
+is a more general approach than ``jump``. :class:`~pcg64.PCG64`,
+:class:`~threefry.ThreeFry` and :class:`~philox.Philox`
+support ``advance``, and since these also support independent
+streams, it is not usually necessary to use ``advance``.
+
+Advancing a PRNG updates the underlying PRNG state as-if a given number of
+calls to the underlying PRNG have been made. In general there is not a
+one-to-one relationship between the number output random values from a
+particular distribution and the number of draws from the core PRNG.
+This occurs for two reasons:
+
+* The random values are simulated using a rejection-based method
+ and so, on average, more than one value from the underlying
+ PRNG is required to generate an single draw.
+* The number of bits required to generate a simulated value
+ differs from the number of bits generated by the underlying
+ PRNG. For example, two 16-bit integer values can be simulated
+ from a single draw of a 32-bit PRNG.
+
+Advancing the PRNG state resets any pre-computed random numbers. This is
+required to ensure exact reproducibility.
+
+This example uses ``advance`` to advance a :class:`~pcg64.PCG64`
+generator 2 ** 127 steps to set a sequence of random number generators.
+
+.. code-block:: python
+
+ from numpy.random import PCG64
+ brng = PCG64()
+ brng_copy = PCG64()
+ brng_copy.state = brng.state
+
+ advance = 2**127
+ brngs = [brng]
+ for _ in range(9):
+ brng_copy.advance(advance)
+ brng = PCG64()
+ brng.state = brng_copy.state
+ brngs.append(brng)
+
+.. end block
+
diff --git a/doc/source/reference/random/performance.py b/doc/source/reference/random/performance.py
new file mode 100644
index 000000000..12cbbc5d3
--- /dev/null
+++ b/doc/source/reference/random/performance.py
@@ -0,0 +1,74 @@
+from collections import OrderedDict
+from timeit import repeat
+
+import numpy as np
+import pandas as pd
+
+from randomgen import MT19937, DSFMT, ThreeFry, PCG64, Xoroshiro128, \
+ Xorshift1024, Philox, Xoshiro256StarStar, Xoshiro512StarStar
+
+PRNGS = [DSFMT, MT19937, Philox, PCG64, ThreeFry, Xoroshiro128, Xorshift1024,
+ Xoshiro256StarStar, Xoshiro512StarStar]
+
+funcs = {'32-bit Unsigned Ints': 'random_uintegers(size=1000000,bits=32)',
+ '64-bit Unsigned Ints': 'random_uintegers(size=1000000,bits=32)',
+ 'Uniforms': 'random_sample(size=1000000)',
+ 'Complex Normals': 'complex_normal(size=1000000)',
+ 'Normals': 'standard_normal(size=1000000)',
+ 'Exponentials': 'standard_exponential(size=1000000)',
+ 'Gammas': 'standard_gamma(3.0,size=1000000)',
+ 'Binomials': 'binomial(9, .1, size=1000000)',
+ 'Laplaces': 'laplace(size=1000000)',
+ 'Poissons': 'poisson(3.0, size=1000000)', }
+
+setup = """
+from randomgen import {prng}
+rg = {prng}().generator
+"""
+
+test = "rg.{func}"
+table = OrderedDict()
+for prng in PRNGS:
+ print(prng)
+ col = OrderedDict()
+ for key in funcs:
+ t = repeat(test.format(func=funcs[key]),
+ setup.format(prng=prng().__class__.__name__),
+ number=1, repeat=3)
+ col[key] = 1000 * min(t)
+ col = pd.Series(col)
+ table[prng().__class__.__name__] = col
+
+npfuncs = OrderedDict()
+npfuncs.update(funcs)
+npfuncs['32-bit Unsigned Ints'] = 'randint(2**32,dtype="uint32",size=1000000)'
+npfuncs['64-bit Unsigned Ints'] = 'tomaxint(size=1000000)'
+del npfuncs['Complex Normals']
+setup = """
+from numpy.random import RandomState
+rg = RandomState()
+"""
+col = {}
+for key in npfuncs:
+ t = repeat(test.format(func=npfuncs[key]),
+ setup.format(prng=prng().__class__.__name__),
+ number=1, repeat=3)
+ col[key] = 1000 * min(t)
+table['NumPy'] = pd.Series(col)
+
+table = pd.DataFrame(table)
+table = table.reindex(table.mean(1).sort_values().index)
+order = np.log(table).mean().sort_values().index
+table = table.T
+table = table.reindex(order)
+table = table.T
+print(table.to_csv(float_format='%0.1f'))
+
+rel = table.loc[:, ['NumPy']].values @ np.ones((1, table.shape[1])) / table
+rel.pop(rel.columns[0])
+rel = rel.T
+rel['Overall'] = np.exp(np.log(rel).mean(1))
+rel *= 100
+rel = np.round(rel)
+rel = rel.T
+print(rel.to_csv(float_format='%0d'))
diff --git a/doc/source/reference/random/performance.rst b/doc/source/reference/random/performance.rst
new file mode 100644
index 000000000..321d49454
--- /dev/null
+++ b/doc/source/reference/random/performance.rst
@@ -0,0 +1,77 @@
+Performance
+-----------
+
+.. py:module:: numpy.random
+
+.. currentmodule:: numpy.random
+
+Recommendation
+**************
+The recommended generator for single use is
+:class:`~xoroshiro128.Xoroshiro128`. The recommended generator
+for use in large-scale parallel applications is
+:class:`~xorshift1024.Xorshift1024`
+where the `jump` method is used to advance the state. For very large scale
+applications -- requiring 1,000+ independent streams,
+:class:`~pcg64.PCG64` or :class:`~threefry.ThreeFry` are
+the best choices.
+
+Timings
+*******
+
+The timings below are the time in ms to produce 1,000,000 random values from a
+specific distribution. :class:`~xoroshiro128.Xoroshiro128` is the
+fastest, followed by :class:`~xorshift1024.Xorshift1024` and
+:class:`~pcg64.PCG64`. The original :class:`~mt19937.MT19937`
+generator is much slower since it requires 2 32-bit values to equal the output
+of the faster generators.
+
+Integer performance has a similar ordering although `dSFMT` is slower since
+it generates 53-bit floating point values rather than integer values. On the
+other hand, it is very fast for uniforms, although slower than `xoroshiro128+`.
+
+The pattern is similar for other, more complex generators. The normal
+performance of NumPy's MT19937 is much lower than the other since it
+uses the Box-Muller transformation rather than the Ziggurat generator. The
+performance gap for Exponentials is also large due to the cost of computing
+the log function to invert the CDF.
+
+.. csv-table::
+ :header: ,Xoroshiro128,Xorshift1024,PCG64,DSFMT,MT19937,Philox,ThreeFry,NumPy
+ :widths: 14,14,14,14,14,14,14,14,14
+
+ 32-bit Unsigned Ints,3.0,3.0,3.0,3.5,3.7,6.8,6.6,3.3
+ 64-bit Unsigned Ints,2.6,3.0,3.1,3.4,3.8,6.9,6.6,8.8
+ Uniforms,3.2,3.8,4.4,5.0,7.4,8.9,9.9,8.8
+ Normals,11.0,13.9,13.7,15.8,16.9,17.8,18.8,63.0
+ Exponentials,7.0,8.4,9.0,11.2,12.5,14.1,15.0,102.2
+ Binomials,20.9,22.6,22.0,21.2,26.7,27.7,29.2,26.5
+ Complex Normals,23.2,28.7,29.1,33.2,35.4,37.6,38.6,
+ Gammas,35.3,38.6,39.2,41.3,46.7,49.4,51.2,98.8
+ Laplaces,97.8,99.9,99.8,96.2,104.1,104.6,104.8,104.1
+ Poissons,104.8,113.2,113.3,107.6,129.7,135.6,138.1,131.9
+
+
+The next table presents the performance relative to `xoroshiro128+` in
+percentage. The overall performance was computed using a geometric mean.
+
+.. csv-table::
+ :header: ,Xorshift1024,PCG64,DSFMT,MT19937,Philox,ThreeFry,NumPy
+ :widths: 14,14,14,14,14,14,14,14
+
+ 32-bit Unsigned Ints,102,99,118,125,229,221,111
+ 64-bit Unsigned Ints,114,116,129,143,262,248,331
+ Uniforms,116,137,156,231,275,306,274
+ Normals,126,124,143,153,161,170,572
+ Exponentials,121,130,161,179,203,215,1467
+ Binomials,108,105,101,128,133,140,127
+ Complex Normals,124,125,143,153,162,166,
+ Gammas,109,111,117,132,140,145,280
+ Laplaces,102,102,98,106,107,107,106
+ Poissons,108,108,103,124,129,132,126
+ Overall,113,115,125,144,172,177,251
+
+
+.. note::
+
+ All timings were taken using Linux on a i5-3570 processor.
diff --git a/doc/source/reference/random/references.rst b/doc/source/reference/random/references.rst
new file mode 100644
index 000000000..0dc99868f
--- /dev/null
+++ b/doc/source/reference/random/references.rst
@@ -0,0 +1,5 @@
+References
+----------
+
+.. [Lemire] Daniel Lemire., "Fast Random Integer Generation in an Interval",
+ CoRR, Aug. 13, 2018, http://arxiv.org/abs/1805.10941.