summaryrefslogtreecommitdiff
path: root/numpy/random
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/random')
-rw-r--r--numpy/random/_generator.pyx14
-rw-r--r--numpy/random/include/aligned_malloc.h2
-rw-r--r--numpy/random/mtrand.pyx11
-rw-r--r--numpy/random/setup.py16
-rw-r--r--numpy/random/src/distributions/distributions.c6
-rw-r--r--numpy/random/src/distributions/random_hypergeometric.c2
-rw-r--r--numpy/random/src/pcg64/pcg64.c3
-rw-r--r--numpy/random/tests/test_direct.py22
-rw-r--r--numpy/random/tests/test_generator_mt19937_regressions.py2
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())