diff --git a/README.rst b/README.rst index 335a678b1..a0e35d584 100644 --- a/README.rst +++ b/README.rst @@ -1,10 +1,7 @@ RandomGen ========= -`Travis Build Status `__ -`Appveyor Build -Status `__ -`PyPI version `__ +|Travis Build Status| |Appveyor Build Status| |PyPI version| Random Number Generator using settable Basic RNG interface for future NumPy RandomState evolution. @@ -292,3 +289,10 @@ NumPy’s mt19937. ThreeFry32 97.0% Xoroshiro128 477.4% Xorshift1024 360.7% + +.. |Travis Build Status| image:: https://travis-ci.org/bashtage/randomgen.svg?branch=master + :target: https://travis-ci.org/bashtage/randomgen +.. |Appveyor Build Status| image:: https://ci.appveyor.com/api/projects/status/odc5c4ukhru5xicl/branch/master?svg=true + :target: https://ci.appveyor.com/project/bashtage/randomgen/branch/master +.. |PyPI version| image:: https://badge.fury.io/py/randomgen.svg + :target: https://pypi.org/project/randomgen/ diff --git a/doc/source/change-log.rst b/doc/source/change-log.rst index 608492528..9cb5f0128 100644 --- a/doc/source/change-log.rst +++ b/doc/source/change-log.rst @@ -1,9 +1,10 @@ Change Log ---------- -Changes since v1.14 -=================== - +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 @@ -12,5 +13,3 @@ Changes since v1.14 - Switch to array-fillers for 0 parameter distribution to improve performance - Small changes to build on manylinux - Build wheels using multibuild - - diff --git a/randomgen/examples/numba/extending.py b/randomgen/examples/numba/extending.py index 866b4070d..4dafeb5c4 100644 --- a/randomgen/examples/numba/extending.py +++ b/randomgen/examples/numba/extending.py @@ -68,10 +68,10 @@ def normals(n, state): start = dt.datetime.now() normalsj(1000000, state_addr) ms = 1000 * (dt.datetime.now() - start).total_seconds() -print('1,000,000 Box-Muller (numba/Xoroshiro128) randoms in ' +print('1,000,000 Polar-transform (numba/Xoroshiro128) randoms in ' '{ms:0.1f}ms'.format(ms=ms)) start = dt.datetime.now() np.random.standard_normal(1000000) ms = 1000 * (dt.datetime.now() - start).total_seconds() -print('1,000,000 Box-Muller (NumPy) randoms in {ms:0.1f}ms'.format(ms=ms)) +print('1,000,000 Polar-transform (NumPy) randoms in {ms:0.1f}ms'.format(ms=ms)) diff --git a/randomgen/generator.pyx b/randomgen/generator.pyx index 88ca7090b..a752aa84c 100644 --- a/randomgen/generator.pyx +++ b/randomgen/generator.pyx @@ -798,7 +798,7 @@ cdef class RandomGenerator: else: pop_size = a.shape[0] if pop_size is 0 and np.prod(size) != 0: - raise ValueError("a cannot be empty unless no samples are taken") + raise ValueError("'a' cannot be empty unless no samples are taken") if p is not None: d = len(p) @@ -2102,7 +2102,7 @@ cdef class RandomGenerator: Examples -------- From Dalgaard page 83 [1]_, suppose the daily energy intake for 11 - women in Kj is: + women in kilojoules (kJ) is: >>> intake = np.array([5260., 5470, 5640, 6180, 6390, 6515, 6805, 7515, \\ ... 7515, 8230, 8770]) @@ -3606,12 +3606,12 @@ cdef class RandomGenerator: ----- The probability density for the Hypergeometric distribution is - .. math:: P(x) = \\frac{\\binom{m}{n}\\binom{N-m}{n-x}}{\\binom{N}{n}}, + .. math:: P(x) = \\frac{\\binom{g}{x}\\binom{b}{n-x}}{\\binom{g+b}{n}}, - where :math:`0 \\le x \\le m` and :math:`n+m-N \\le x \\le n` + where :math:`0 \\le x \\le n` and :math:`n-b \\le x \\le g` - for P(x) the probability of x successes, n = ngood, m = nbad, and - N = number of samples. + for P(x) the probability of x successes, g = ngood, b = nbad, and + n = number of samples. Consider an urn with black and white marbles in it, ngood of them black and nbad are white. If you draw nsample balls without diff --git a/randomgen/legacy/_legacy.pyx b/randomgen/legacy/_legacy.pyx index c264bd904..a45ee829f 100644 --- a/randomgen/legacy/_legacy.pyx +++ b/randomgen/legacy/_legacy.pyx @@ -171,14 +171,15 @@ cdef class _LegacyGenerator: Get or set the augmented state Returns the basic RNGs state as well as two values added to track - normal generation using the Box-Muller method. + normal generation using the Polar (Box-Muller-like) method. Returns ------- state : dict Dictionary containing the information required to describe the state of the Basic RNG with two additional fields, gauss and - has_gauss, required to store generated Box-Muller normals. + has_gauss, required to store generated Polar transformation + (Box-Muller-like) normals. """ st = self._basicrng.state st['has_gauss'] = self._aug_state.has_gauss diff --git a/randomgen/src/distributions/distributions.c b/randomgen/src/distributions/distributions.c index a0966b6b0..26b6232c2 100644 --- a/randomgen/src/distributions/distributions.c +++ b/randomgen/src/distributions/distributions.c @@ -49,9 +49,9 @@ double random_gauss(brng_t *brng_state) { r2 = x1 * x1 + x2 * x2; } while (r2 >= 1.0 || r2 == 0.0); - // Box-Muller transform + /* Polar method, a more efficient version of the Box-Muller approach. f = sqrt(-2.0 * log(r2) / r2); - // Keep for next call + /* Keep for next call brng_state->gauss = f * x1; brng_state->has_gauss = true; return f * x2; @@ -73,9 +73,9 @@ float random_gauss_f(brng_t *brng_state) { r2 = x1 * x1 + x2 * x2; } while (r2 >= 1.0 || r2 == 0.0); - // Box-Muller transform + /* Polar method, a more efficient version of the Box-Muller approach. f = sqrtf(-2.0f * logf(r2) / r2); - // Keep for next call + /* Keep for next call brng_state->gauss_f = f * x1; brng_state->has_gauss_f = true; return f * x2; @@ -108,7 +108,7 @@ static NPY_INLINE double standard_exponential_zig(brng_t *brng_state) { ri >>= 8; x = ri * we_double[idx]; if (ri < ke_double[idx]) { - return x; // 98.9% of the time we return here 1st try + return x; /* 98.9% of the time we return here 1st try */ } return standard_exponential_zig_unlikely(brng_state, idx, x); } @@ -150,7 +150,7 @@ static NPY_INLINE float standard_exponential_zig_f(brng_t *brng_state) { ri >>= 8; x = ri * we_float[idx]; if (ri < ke_float[idx]) { - return x; // 98.9% of the time we return here 1st try + return x; /* 98.9% of the time we return here 1st try */ } return standard_exponential_zig_unlikely_f(brng_state, idx, x); } @@ -176,7 +176,7 @@ static NPY_INLINE double next_gauss_zig(brng_t *brng_state) { if (sign & 0x1) x = -x; if (rabs < ki_double[idx]) - return x; // # 99.3% of the time return here + return x; /* 99.3% of the time return here */ if (idx == 0) { for (;;) { xx = -ziggurat_nor_inv_r * log(next_double(brng_state)); @@ -220,7 +220,7 @@ float random_gauss_zig_f(brng_t *brng_state) { if (sign & 0x1) x = -x; if (rabs < ki_float[idx]) - return x; // # 99.3% of the time return here + return x; /* # 99.3% of the time return here */ if (idx == 0) { for (;;) { xx = -ziggurat_nor_inv_r_f * logf(next_float(brng_state)); diff --git a/randomgen/src/legacy/distributions-boxmuller.c b/randomgen/src/legacy/distributions-boxmuller.c index 8d3d94095..7ad1742cc 100644 --- a/randomgen/src/legacy/distributions-boxmuller.c +++ b/randomgen/src/legacy/distributions-boxmuller.c @@ -19,7 +19,7 @@ double legacy_gauss(aug_brng_t *aug_state) { r2 = x1 * x1 + x2 * x2; } while (r2 >= 1.0 || r2 == 0.0); - /* Box-Muller transform */ + /* Polar method, a more efficient version of the Box-Muller approach. */ f = sqrt(-2.0 * log(r2) / r2); /* Keep for next call */ aug_state->gauss = f * x1; diff --git a/randomgen/src/mt19937/randomkit.c b/randomgen/src/mt19937/randomkit.c index 947d2adb1..f8ed4b49e 100644 --- a/randomgen/src/mt19937/randomkit.c +++ b/randomgen/src/mt19937/randomkit.c @@ -568,7 +568,7 @@ double rk_gauss(rk_state *state) { r2 = x1 * x1 + x2 * x2; } while (r2 >= 1.0 || r2 == 0.0); - /* Box-Muller transform */ + /* Polar method, a more efficient version of the Box-Muller approach. */ f = sqrt(-2.0 * log(r2) / r2); /* Keep for next call */ state->gauss = f * x1; diff --git a/randomgen/tests/test_against_numpy.py b/randomgen/tests/test_against_numpy.py index 46350cdd0..ea2656e83 100644 --- a/randomgen/tests/test_against_numpy.py +++ b/randomgen/tests/test_against_numpy.py @@ -4,6 +4,7 @@ import randomgen from randomgen import RandomGenerator, MT19937 +from randomgen._testing import suppress_warnings from randomgen.legacy import LegacyGenerator @@ -263,9 +264,11 @@ def test_vonmises(self): def test_random_integers(self): self._set_common_state() self._is_state_common() - compare_2_input(self.nprs.random_integers, - self.rg.random_integers, - is_scalar=True) + with suppress_warnings() as sup: + sup.record(DeprecationWarning) + compare_2_input(self.nprs.random_integers, + self.rg.random_integers, + is_scalar=True) self._is_state_common() def test_binomial(self): diff --git a/randomgen/tests/test_direct.py b/randomgen/tests/test_direct.py index c6cd00bd5..be4f533ea 100644 --- a/randomgen/tests/test_direct.py +++ b/randomgen/tests/test_direct.py @@ -146,7 +146,7 @@ def test_raw(self): uints = rs.random_raw(1000) assert_equal(uints, self.data2['data']) - @pytest.mark.skip(reason='Box-Muller no longer supported') + @pytest.mark.skip(reason='Polar transform no longer supported') def test_gauss_inv(self): n = 25 rs = RandomGenerator(self.brng(*self.data1['seed'])) @@ -352,7 +352,7 @@ def test_uniform_double(self): assert_equal(uniform_from_dsfmt(self.data2['data']), rs.random_sample(1000)) - @pytest.mark.skip(reason='Box-Muller no longer supported') + @pytest.mark.skip(reason='Polar transform no longer supported') def test_gauss_inv(self): n = 25 rs = RandomGenerator(self.brng(*self.data1['seed'])) diff --git a/randomgen/tests/test_numpy_mt19937.py b/randomgen/tests/test_numpy_mt19937.py index 6b3104d64..2ab6bd2d3 100644 --- a/randomgen/tests/test_numpy_mt19937.py +++ b/randomgen/tests/test_numpy_mt19937.py @@ -567,12 +567,13 @@ def test_choice_return_shape(self): assert_(mt19937.choice(np.arange(6), s, replace=True).shape, s) # Check zero-size - assert_equal(mt19937.randint(0,0,(3,0,4)).shape, (3,0,4)) - assert_equal(mt19937.randint(0,-10,0).shape, (0,)) - assert_equal(mt19937.choice(0,0).shape, (0,)) - assert_equal(mt19937.choice([],(0,)).shape, (0,)) + assert_equal(mt19937.randint(0, 0, size=(3, 0, 4)).shape, (3, 0, 4)) + assert_equal(mt19937.randint(0, -10, size=0).shape, (0,)) + assert_equal(mt19937.randint(10, 10, size=0).shape, (0,)) + assert_equal(mt19937.choice(0, size=0).shape, (0,)) + assert_equal(mt19937.choice([], size=(0,)).shape, (0,)) assert_equal(mt19937.choice(['a', 'b'], size=(3, 0, 4)).shape, (3, 0, 4)) - assert_raises(ValueError, mt19937.choice, [], 10) + assert_raises(ValueError, mt19937.choice, [], 10) def test_bytes(self): mt19937.seed(self.seed) diff --git a/randomgen/tests/test_smoke.py b/randomgen/tests/test_smoke.py index 34f95bc10..99f218181 100644 --- a/randomgen/tests/test_smoke.py +++ b/randomgen/tests/test_smoke.py @@ -8,6 +8,7 @@ from numpy.testing import assert_almost_equal, assert_equal, assert_, \ assert_array_equal +from randomgen._testing import suppress_warnings from randomgen import RandomGenerator, MT19937, DSFMT, ThreeFry32, ThreeFry, \ PCG32, PCG64, Philox, Xoroshiro128, Xorshift1024 from randomgen import entropy @@ -467,7 +468,9 @@ def test_randint(self): assert_(len(vals) == 10) def test_random_integers(self): - vals = self.rg.random_integers(10, 20, 10) + with suppress_warnings() as sup: + sup.record(DeprecationWarning) + vals = self.rg.random_integers(10, 20, 10) assert_(len(vals) == 10) def test_rayleigh(self):