diff options
Diffstat (limited to 'numpy/random')
| -rw-r--r-- | numpy/random/_generator.pyx | 14 | ||||
| -rw-r--r-- | numpy/random/include/aligned_malloc.h | 2 | ||||
| -rw-r--r-- | numpy/random/mtrand.pyx | 11 | ||||
| -rw-r--r-- | numpy/random/setup.py | 16 | ||||
| -rw-r--r-- | numpy/random/src/distributions/distributions.c | 6 | ||||
| -rw-r--r-- | numpy/random/src/distributions/random_hypergeometric.c | 2 | ||||
| -rw-r--r-- | numpy/random/src/pcg64/pcg64.c | 3 | ||||
| -rw-r--r-- | numpy/random/tests/test_direct.py | 22 | ||||
| -rw-r--r-- | numpy/random/tests/test_generator_mt19937_regressions.py | 2 |
9 files changed, 59 insertions, 19 deletions
diff --git a/numpy/random/_generator.pyx b/numpy/random/_generator.pyx index 60b6bfc72..5347ea125 100644 --- a/numpy/random/_generator.pyx +++ b/numpy/random/_generator.pyx @@ -876,8 +876,10 @@ cdef class Generator: greater than or equal to low. The default value is 0. high : float or array_like of floats Upper boundary of the output interval. All values generated will be - less than high. high - low must be non-negative. The default value - is 1.0. + less than high. The high limit may be included in the returned array of + floats due to floating-point rounding in the equation + ``low + (high-low) * random_sample()``. high - low must be + non-negative. The default value is 1.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), @@ -2095,7 +2097,7 @@ cdef class Generator: Raises ------ ValueError - If a < 1. + If a <= 0. Notes ----- @@ -3624,7 +3626,7 @@ cdef class Generator: from numpy.linalg import cholesky l = cholesky(cov) - # make sure check_valid is ignored whe method == 'cholesky' + # make sure check_valid is ignored when method == 'cholesky' # since the decomposition will have failed if cov is not valid. if check_valid != 'ignore' and method != 'cholesky': if check_valid != 'warn' and check_valid != 'raise': @@ -4441,7 +4443,7 @@ cdef class Generator: # Fast, statically typed path: shuffle the underlying buffer. # Only for non-empty, 1d objects of class ndarray (subclasses such # as MaskedArrays may not support this approach). - x_ptr = <char*><size_t>np.PyArray_DATA(x) + x_ptr = np.PyArray_BYTES(x) stride = x.strides[0] itemsize = x.dtype.itemsize # As the array x could contain python objects we use a buffer @@ -4449,7 +4451,7 @@ cdef class Generator: # within the buffer and erroneously decrementing it's refcount # when the function exits. buf = np.empty(itemsize, dtype=np.int8) # GC'd at function exit - buf_ptr = <char*><size_t>np.PyArray_DATA(buf) + buf_ptr = np.PyArray_BYTES(buf) if x.dtype.hasobject: with self.lock: _shuffle_raw_wrap(&self._bitgen, n, 1, itemsize, stride, diff --git a/numpy/random/include/aligned_malloc.h b/numpy/random/include/aligned_malloc.h index ea24f6d23..43f68253d 100644 --- a/numpy/random/include/aligned_malloc.h +++ b/numpy/random/include/aligned_malloc.h @@ -1,7 +1,7 @@ #ifndef _RANDOMDGEN__ALIGNED_MALLOC_H_ #define _RANDOMDGEN__ALIGNED_MALLOC_H_ -#include "Python.h" +#include <Python.h> #include "numpy/npy_common.h" #define NPY_MEMALIGN 16 /* 16 for SSE2, 32 for AVX, 64 for Xeon Phi */ diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx index c9d8ee8e3..81a526ab4 100644 --- a/numpy/random/mtrand.pyx +++ b/numpy/random/mtrand.pyx @@ -1033,7 +1033,10 @@ cdef class RandomState: greater than or equal to low. The default value is 0. high : float or array_like of floats Upper boundary of the output interval. All values generated will be - less than or equal to high. The default value is 1.0. + less than or equal to high. The high limit may be included in the + returned array of floats due to floating-point rounding in the + equation ``low + (high-low) * random_sample()``. The default value + is 1.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), @@ -2524,7 +2527,7 @@ cdef class RandomState: Raises ------ ValueError - If a < 1. + If a <= 0. See Also -------- @@ -4472,7 +4475,7 @@ cdef class RandomState: # Fast, statically typed path: shuffle the underlying buffer. # Only for non-empty, 1d objects of class ndarray (subclasses such # as MaskedArrays may not support this approach). - x_ptr = <char*><size_t>np.PyArray_DATA(x) + x_ptr = np.PyArray_BYTES(x) stride = x.strides[0] itemsize = x.dtype.itemsize # As the array x could contain python objects we use a buffer @@ -4480,7 +4483,7 @@ cdef class RandomState: # within the buffer and erroneously decrementing it's refcount # when the function exits. buf = np.empty(itemsize, dtype=np.int8) # GC'd at function exit - buf_ptr = <char*><size_t>np.PyArray_DATA(buf) + buf_ptr = np.PyArray_BYTES(buf) with self.lock: # We trick gcc into providing a specialized implementation for # the most common case, yielding a ~33% performance improvement. diff --git a/numpy/random/setup.py b/numpy/random/setup.py index dce9a101e..866c0cb2f 100644 --- a/numpy/random/setup.py +++ b/numpy/random/setup.py @@ -65,12 +65,26 @@ def configuration(parent_package='', top_path=None): 'src/distributions/random_mvhg_marginals.c', 'src/distributions/random_hypergeometric.c', ] + + def gl_if_msvc(build_cmd): + """ Add flag if we are using MSVC compiler + + We can't see this in our scope, because we have not initialized the + distutils build command, so use this deferred calculation to run when + we are building the library. + """ + # Keep in sync with numpy/core/setup.py + if build_cmd.compiler.compiler_type == 'msvc': + # explicitly disable whole-program optimization + return ['/GL-'] + return [] + config.add_installed_library('npyrandom', sources=npyrandom_sources, install_dir='lib', build_info={ 'include_dirs' : [], # empty list required for creating npyrandom.h - 'extra_compiler_args' : (['/GL-'] if is_msvc else []), + 'extra_compiler_args': [gl_if_msvc], }) for gen in ['mt19937']: diff --git a/numpy/random/src/distributions/distributions.c b/numpy/random/src/distributions/distributions.c index 9bdfa9bea..adf4db4a7 100644 --- a/numpy/random/src/distributions/distributions.c +++ b/numpy/random/src/distributions/distributions.c @@ -452,7 +452,7 @@ double random_standard_cauchy(bitgen_t *bitgen_state) { } double random_pareto(bitgen_t *bitgen_state, double a) { - return exp(random_standard_exponential(bitgen_state) / a) - 1; + return expm1(random_standard_exponential(bitgen_state) / a); } double random_weibull(bitgen_t *bitgen_state, double a) { @@ -463,7 +463,7 @@ double random_weibull(bitgen_t *bitgen_state, double a) { } double random_power(bitgen_t *bitgen_state, double a) { - return pow(1 - exp(-random_standard_exponential(bitgen_state)), 1. / a); + return pow(-expm1(-random_standard_exponential(bitgen_state)), 1. / a); } double random_laplace(bitgen_t *bitgen_state, double loc, double scale) { @@ -918,7 +918,7 @@ int64_t random_logseries(bitgen_t *bitgen_state, double p) { return 1; } U = next_double(bitgen_state); - q = 1.0 - exp(r * U); + q = -expm1(r * U); if (V <= q * q) { result = (int64_t)floor(1 + log(V) / log(q)); if ((result < 1) || (V == 0.0)) { diff --git a/numpy/random/src/distributions/random_hypergeometric.c b/numpy/random/src/distributions/random_hypergeometric.c index 0da49bd62..d8510bfca 100644 --- a/numpy/random/src/distributions/random_hypergeometric.c +++ b/numpy/random/src/distributions/random_hypergeometric.c @@ -155,7 +155,7 @@ static int64_t hypergeometric_hrua(bitgen_t *bitgen_state, c = sqrt(var + 0.5); /* - * h is 2*s_hat (See Stadlober's theses (1989), Eq. (5.17); or + * h is 2*s_hat (See Stadlober's thesis (1989), Eq. (5.17); or * Stadlober (1990), Eq. 8). s_hat is the scale of the "table mountain" * function that dominates the scaled hypergeometric PMF ("scaled" means * normalized to have a maximum value of 1). diff --git a/numpy/random/src/pcg64/pcg64.c b/numpy/random/src/pcg64/pcg64.c index c623c809b..b9be1e39d 100644 --- a/numpy/random/src/pcg64/pcg64.c +++ b/numpy/random/src/pcg64/pcg64.c @@ -109,8 +109,7 @@ pcg128_t pcg_advance_lcg_128(pcg128_t state, pcg128_t delta, pcg128_t cur_mult, cur_plus = pcg128_mult(pcg128_add(cur_mult, PCG_128BIT_CONSTANT(0u, 1u)), cur_plus); cur_mult = pcg128_mult(cur_mult, cur_mult); - delta.low >>= 1; - delta.low += delta.high & 1; + delta.low = (delta.low >> 1) | (delta.high << 63); delta.high >>= 1; } return pcg128_add(pcg128_mult(acc_mult, state), acc_plus); diff --git a/numpy/random/tests/test_direct.py b/numpy/random/tests/test_direct.py index 29054b70b..ea1ebacb6 100644 --- a/numpy/random/tests/test_direct.py +++ b/numpy/random/tests/test_direct.py @@ -358,6 +358,17 @@ class TestPCG64(Base): assert val_neg == val_pos assert val_big == val_pos + def test_advange_large(self): + rs = Generator(self.bit_generator(38219308213743)) + pcg = rs.bit_generator + state = pcg.state["state"] + initial_state = 287608843259529770491897792873167516365 + assert state["state"] == initial_state + pcg.advance(sum(2**i for i in (96, 64, 32, 16, 8, 4, 2, 1))) + state = pcg.state["state"] + advanced_state = 135275564607035429730177404003164635391 + assert state["state"] == advanced_state + class TestPCG64DXSM(Base): @classmethod @@ -386,6 +397,17 @@ class TestPCG64DXSM(Base): assert val_neg == val_pos assert val_big == val_pos + def test_advange_large(self): + rs = Generator(self.bit_generator(38219308213743)) + pcg = rs.bit_generator + state = pcg.state + initial_state = 287608843259529770491897792873167516365 + assert state["state"]["state"] == initial_state + pcg.advance(sum(2**i for i in (96, 64, 32, 16, 8, 4, 2, 1))) + state = pcg.state["state"] + advanced_state = 277778083536782149546677086420637664879 + assert state["state"] == advanced_state + class TestMT19937(Base): @classmethod diff --git a/numpy/random/tests/test_generator_mt19937_regressions.py b/numpy/random/tests/test_generator_mt19937_regressions.py index 88d2792a6..0227d6502 100644 --- a/numpy/random/tests/test_generator_mt19937_regressions.py +++ b/numpy/random/tests/test_generator_mt19937_regressions.py @@ -1,7 +1,7 @@ from numpy.testing import (assert_, assert_array_equal) import numpy as np import pytest -from numpy.random import Generator, MT19937, RandomState +from numpy.random import Generator, MT19937 mt19937 = Generator(MT19937()) |
