summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--_randomgen/doc/source/change-log.rst11
-rw-r--r--_randomgen/randomgen/common.pxd2
-rw-r--r--_randomgen/randomgen/distributions.pxd2
-rw-r--r--_randomgen/randomgen/dsfmt.pyx18
-rw-r--r--_randomgen/randomgen/generator.pyx38
-rw-r--r--_randomgen/randomgen/legacy/legacy_distributions.pxd2
-rw-r--r--_randomgen/randomgen/mt19937.pyx4
-rw-r--r--_randomgen/randomgen/src/distributions/distributions.c3
-rw-r--r--_randomgen/randomgen/tests/test_direct.py6
-rw-r--r--_randomgen/randomgen/tests/test_numpy_mt19937.py3
-rw-r--r--_randomgen/randomgen/xorshift1024.pyx2
-rw-r--r--_randomgen/randomgen/xoshiro512starstar.pyx4
12 files changed, 73 insertions, 22 deletions
diff --git a/_randomgen/doc/source/change-log.rst b/_randomgen/doc/source/change-log.rst
index 629dd0002..eb884c7f3 100644
--- a/_randomgen/doc/source/change-log.rst
+++ b/_randomgen/doc/source/change-log.rst
@@ -1,5 +1,16 @@
Change Log
----------
+v1.15.2
+=======
+- Fixed a bug that affected :class:`~randomgen.dsfmt.DSFMT` when calling
+ :func:`~randomgen.dsfmt.DSFMT.jump` or :func:`~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 :class:`~randomgen.xoshiro512starstar.Xoshiro512StarStar`
+ and :class:`~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.
v1.15.1
=======
diff --git a/_randomgen/randomgen/common.pxd b/_randomgen/randomgen/common.pxd
index 62163ad62..63a1b3f7d 100644
--- a/_randomgen/randomgen/common.pxd
+++ b/_randomgen/randomgen/common.pxd
@@ -1,3 +1,5 @@
+#cython: language_level=3
+
from __future__ import absolute_import
from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t,
diff --git a/_randomgen/randomgen/distributions.pxd b/_randomgen/randomgen/distributions.pxd
index a50d5d821..35d92db51 100644
--- a/_randomgen/randomgen/distributions.pxd
+++ b/_randomgen/randomgen/distributions.pxd
@@ -1,3 +1,5 @@
+#cython: language_level=3
+
from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t,
int8_t, int16_t, int32_t, int64_t, intptr_t)
import numpy as np
diff --git a/_randomgen/randomgen/dsfmt.pyx b/_randomgen/randomgen/dsfmt.pyx
index c83ade5cd..ee8ef270d 100644
--- a/_randomgen/randomgen/dsfmt.pyx
+++ b/_randomgen/randomgen/dsfmt.pyx
@@ -79,8 +79,8 @@ cdef class DSFMT:
Can be an integer in [0, 2**32-1], array of integers in
[0, 2**32-1] or ``None`` (the default). If `seed` is ``None``,
then ``DSFMT`` will try to read entropy from ``/dev/urandom``
- (or the Windows analog) if available to produce a 64-bit
- seed. If unavailable, a 64-bit hash of the time and process
+ (or the Windows analog) if available to produce a 32-bit
+ seed. If unavailable, a 32-bit hash of the time and process
ID is used.
Notes
@@ -114,7 +114,7 @@ cdef class DSFMT:
The ``DSFMT`` state vector consists of a 384 element array of
64-bit unsigned integers plus a single integer value between 0 and 382
indicating the current position within the main array. The implementation
- used here augments this with a 384 element array of doubles which are used
+ used here augments this with a 382 element array of doubles which are used
to efficiently access the random numbers produced by the dSFMT generator.
``DSFMT`` is seeded using either a single 32-bit unsigned integer
@@ -182,6 +182,10 @@ cdef class DSFMT:
free(self.rng_state)
free(self._brng)
+ cdef _reset_state_variables(self):
+ self.rng_state.buffer_loc = DSFMT_N64
+
+
def _benchmark(self, Py_ssize_t cnt, method=u'uint64'):
cdef Py_ssize_t i
if method==u'uint64':
@@ -206,8 +210,8 @@ cdef class DSFMT:
Can be an integer in [0, 2**32-1], array of integers in
[0, 2**32-1] or ``None`` (the default). If `seed` is ``None``,
then ``DSFMT`` will try to read entropy from ``/dev/urandom``
- (or the Windows analog) if available to produce a 64-bit
- seed. If unavailable, a 64-bit hash of the time and process
+ (or the Windows analog) if available to produce a 32-bit
+ seed. If unavailable, a 32-bit hash of the time and process
ID is used.
Raises
@@ -238,6 +242,8 @@ cdef class DSFMT:
dsfmt_init_by_array(self.rng_state.state,
<uint32_t *>obj.data,
np.PyArray_DIM(obj, 0))
+ # Clear the buffer
+ self._reset_state_variables()
def jump(self, np.npy_intp iter=1):
"""
@@ -258,6 +264,8 @@ cdef class DSFMT:
cdef np.npy_intp i
for i in range(iter):
dsfmt_jump(self.rng_state)
+ # Clear the buffer
+ self._reset_state_variables()
return self
@property
diff --git a/_randomgen/randomgen/generator.pyx b/_randomgen/randomgen/generator.pyx
index 5d239c725..01fa7f1be 100644
--- a/_randomgen/randomgen/generator.pyx
+++ b/_randomgen/randomgen/generator.pyx
@@ -385,9 +385,9 @@ cdef class RandomGenerator:
Parameters
----------
a : float or array_like of floats
- Alpha, non-negative.
+ Alpha, positive (>0).
b : float or array_like of floats
- Beta, non-negative.
+ Beta, positive (>0).
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
@@ -2355,7 +2355,7 @@ cdef class RandomGenerator:
Parameters
----------
a : float or array_like of floats
- Shape of the distribution. Should be greater than zero.
+ Shape parameter of the distribution. Must be nonnegative.
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. If size is ``None`` (default),
@@ -4068,8 +4068,9 @@ cdef class RandomGenerator:
Draw `size` samples of dimension k from a Dirichlet distribution. A
Dirichlet-distributed random variable can be seen as a multivariate
- generalization of a Beta distribution. Dirichlet pdf is the conjugate
- prior of a multinomial in Bayesian inference.
+ generalization of a Beta distribution. The Dirichlet distribution
+ is a conjugate prior of a multinomial distribution in Bayesian
+ inference.
Parameters
----------
@@ -4086,15 +4087,30 @@ cdef class RandomGenerator:
samples : ndarray,
The drawn samples, of shape (size, alpha.ndim).
+ Raises
+ -------
+ ValueError
+ If any value in alpha is less than or equal to zero
+
Notes
-----
- .. math:: X \\approx \\prod_{i=1}^{k}{x^{\\alpha_i-1}_i}
+ The Dirichlet distribution is a distribution over vectors
+ :math:`x` that fulfil the conditions :math:`x_i>0` and
+ :math:`\\sum_{i=1}^k x_i = 1`.
+
+ The probability density function :math:`p` of a
+ Dirichlet-distributed random vector :math:`X` is
+ proportional to
+
+ .. math:: p(x) \\propto \\prod_{i=1}^{k}{x^{\\alpha_i-1}_i},
+
+ where :math:`\\alpha` is a vector containing the positive
+ concentration parameters.
- Uses the following property for computation: for each dimension,
- draw a random sample y_i from a standard gamma generator of shape
- `alpha_i`, then
- :math:`X = \\frac{1}{\\sum_{i=1}^k{y_i}} (y_1, \\ldots, y_n)` is
- Dirichlet distributed.
+ The method uses the following property for computation: let :math:`Y`
+ be a random vector which has components that follow a standard gamma
+ distribution, then :math:`X = \\frac{1}{\\sum_{i=1}^k{Y_i}} Y`
+ is Dirichlet-distributed
References
----------
diff --git a/_randomgen/randomgen/legacy/legacy_distributions.pxd b/_randomgen/randomgen/legacy/legacy_distributions.pxd
index d22d6a73a..e2157f706 100644
--- a/_randomgen/randomgen/legacy/legacy_distributions.pxd
+++ b/_randomgen/randomgen/legacy/legacy_distributions.pxd
@@ -1,3 +1,5 @@
+#cython: language_level=3
+
from libc.stdint cimport uint64_t
import numpy as np
diff --git a/_randomgen/randomgen/mt19937.pyx b/_randomgen/randomgen/mt19937.pyx
index 14ab24f39..207ebc4bd 100644
--- a/_randomgen/randomgen/mt19937.pyx
+++ b/_randomgen/randomgen/mt19937.pyx
@@ -206,8 +206,8 @@ cdef class MT19937:
Can be an integer in [0, 2**32-1], array of integers in
[0, 2**32-1] or ``None`` (the default). If `seed` is ``None``,
then ``MT19937`` will try to read entropy from ``/dev/urandom``
- (or the Windows analog) if available to produce a 64-bit
- seed. If unavailable, a 64-bit hash of the time and process
+ (or the Windows analog) if available to produce a 32-bit
+ seed. If unavailable, a 32-bit hash of the time and process
ID is used.
Raises
diff --git a/_randomgen/randomgen/src/distributions/distributions.c b/_randomgen/randomgen/src/distributions/distributions.c
index e04259136..4e7493afa 100644
--- a/_randomgen/randomgen/src/distributions/distributions.c
+++ b/_randomgen/randomgen/src/distributions/distributions.c
@@ -573,6 +573,9 @@ double random_pareto(brng_t *brng_state, double a) {
}
double random_weibull(brng_t *brng_state, double a) {
+ if (a == 0.0) {
+ return 0.0;
+ }
return pow(standard_exponential_zig(brng_state), 1. / a);
}
diff --git a/_randomgen/randomgen/tests/test_direct.py b/_randomgen/randomgen/tests/test_direct.py
index ee69d5416..5d251a3b7 100644
--- a/_randomgen/randomgen/tests/test_direct.py
+++ b/_randomgen/randomgen/tests/test_direct.py
@@ -428,6 +428,12 @@ class TestDSFMT(Base):
assert_allclose(uniforms, vals)
assert_equal(uniforms.dtype, np.float32)
+ def test_buffer_reset(self):
+ rs = RandomGenerator(self.brng(*self.data1['seed']))
+ u = rs.random_sample(1)
+ rs.seed(*self.data1['seed'])
+ assert rs.state['buffer_loc'] == 382
+
class TestThreeFry32(Base):
@classmethod
diff --git a/_randomgen/randomgen/tests/test_numpy_mt19937.py b/_randomgen/randomgen/tests/test_numpy_mt19937.py
index 888baf92f..df458f2ee 100644
--- a/_randomgen/randomgen/tests/test_numpy_mt19937.py
+++ b/_randomgen/randomgen/tests/test_numpy_mt19937.py
@@ -1104,7 +1104,8 @@ class TestRandomDist(object):
assert_array_almost_equal(actual, desired, decimal=15)
def test_weibull_0(self):
- assert_equal(mt19937.weibull(a=0), 0)
+ mt19937.seed(self.seed)
+ assert_equal(mt19937.weibull(a=0, size=12), np.zeros(12))
assert_raises(ValueError, mt19937.weibull, a=-0.)
def test_zipf(self):
diff --git a/_randomgen/randomgen/xorshift1024.pyx b/_randomgen/randomgen/xorshift1024.pyx
index bf8f32e90..8341985b4 100644
--- a/_randomgen/randomgen/xorshift1024.pyx
+++ b/_randomgen/randomgen/xorshift1024.pyx
@@ -234,7 +234,7 @@ cdef class Xorshift1024:
try:
state = random_entropy(32)
except RuntimeError:
- state = random_entropy(4, 'fallback')
+ state = random_entropy(32, 'fallback')
state = state.view(np.uint64)
else:
state = seed_by_array(seed, 16)
diff --git a/_randomgen/randomgen/xoshiro512starstar.pyx b/_randomgen/randomgen/xoshiro512starstar.pyx
index b4ab76158..17fe3c420 100644
--- a/_randomgen/randomgen/xoshiro512starstar.pyx
+++ b/_randomgen/randomgen/xoshiro512starstar.pyx
@@ -201,9 +201,9 @@ cdef class Xoshiro512StarStar:
ub = 2 ** 64
if seed is None:
try:
- state = random_entropy(2 * 8)
+ state = random_entropy(16)
except RuntimeError:
- state = random_entropy(8, 'fallback')
+ state = random_entropy(16, 'fallback')
state = state.view(np.uint64)
else:
state = seed_by_array(seed, 8)