summaryrefslogtreecommitdiff
path: root/numpy/random/mtrand/mtrand.pyx
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/random/mtrand/mtrand.pyx')
-rw-r--r--numpy/random/mtrand/mtrand.pyx933
1 files changed, 542 insertions, 391 deletions
diff --git a/numpy/random/mtrand/mtrand.pyx b/numpy/random/mtrand/mtrand.pyx
index 84b52079d..55138cba7 100644
--- a/numpy/random/mtrand/mtrand.pyx
+++ b/numpy/random/mtrand/mtrand.pyx
@@ -55,65 +55,66 @@ cdef extern from "randomkit.h":
void rk_seed(unsigned long seed, rk_state *state)
rk_error rk_randomseed(rk_state *state)
unsigned long rk_random(rk_state *state)
- long rk_long(rk_state *state)
- unsigned long rk_ulong(rk_state *state)
- unsigned long rk_interval(unsigned long max, rk_state *state)
- double rk_double(rk_state *state)
- void rk_fill(void *buffer, size_t size, rk_state *state)
+ long rk_long(rk_state *state) nogil
+ unsigned long rk_ulong(rk_state *state) nogil
+ unsigned long rk_interval(unsigned long max, rk_state *state) nogil
+ double rk_double(rk_state *state) nogil
+ void rk_fill(void *buffer, size_t size, rk_state *state) nogil
rk_error rk_devfill(void *buffer, size_t size, int strong)
rk_error rk_altfill(void *buffer, size_t size, int strong,
- rk_state *state)
- double rk_gauss(rk_state *state)
+ rk_state *state) nogil
+ double rk_gauss(rk_state *state) nogil
cdef extern from "distributions.h":
-
- double rk_normal(rk_state *state, double loc, double scale)
- double rk_standard_exponential(rk_state *state)
- double rk_exponential(rk_state *state, double scale)
- double rk_uniform(rk_state *state, double loc, double scale)
- double rk_standard_gamma(rk_state *state, double shape)
- double rk_gamma(rk_state *state, double shape, double scale)
- double rk_beta(rk_state *state, double a, double b)
- double rk_chisquare(rk_state *state, double df)
- double rk_noncentral_chisquare(rk_state *state, double df, double nonc)
- double rk_f(rk_state *state, double dfnum, double dfden)
- double rk_noncentral_f(rk_state *state, double dfnum, double dfden, double nonc)
- double rk_standard_cauchy(rk_state *state)
- double rk_standard_t(rk_state *state, double df)
- double rk_vonmises(rk_state *state, double mu, double kappa)
- double rk_pareto(rk_state *state, double a)
- double rk_weibull(rk_state *state, double a)
- double rk_power(rk_state *state, double a)
- double rk_laplace(rk_state *state, double loc, double scale)
- double rk_gumbel(rk_state *state, double loc, double scale)
- double rk_logistic(rk_state *state, double loc, double scale)
- double rk_lognormal(rk_state *state, double mode, double sigma)
- double rk_rayleigh(rk_state *state, double mode)
- double rk_wald(rk_state *state, double mean, double scale)
- double rk_triangular(rk_state *state, double left, double mode, double right)
-
- long rk_binomial(rk_state *state, long n, double p)
- long rk_binomial_btpe(rk_state *state, long n, double p)
- long rk_binomial_inversion(rk_state *state, long n, double p)
- long rk_negative_binomial(rk_state *state, double n, double p)
- long rk_poisson(rk_state *state, double lam)
- long rk_poisson_mult(rk_state *state, double lam)
- long rk_poisson_ptrs(rk_state *state, double lam)
- long rk_zipf(rk_state *state, double a)
- long rk_geometric(rk_state *state, double p)
- long rk_hypergeometric(rk_state *state, long good, long bad, long sample)
- long rk_logseries(rk_state *state, double p)
-
-ctypedef double (* rk_cont0)(rk_state *state)
-ctypedef double (* rk_cont1)(rk_state *state, double a)
-ctypedef double (* rk_cont2)(rk_state *state, double a, double b)
-ctypedef double (* rk_cont3)(rk_state *state, double a, double b, double c)
-
-ctypedef long (* rk_disc0)(rk_state *state)
-ctypedef long (* rk_discnp)(rk_state *state, long n, double p)
-ctypedef long (* rk_discdd)(rk_state *state, double n, double p)
-ctypedef long (* rk_discnmN)(rk_state *state, long n, long m, long N)
-ctypedef long (* rk_discd)(rk_state *state, double a)
+ # do not need the GIL, but they do need a lock on the state !! */
+
+ double rk_normal(rk_state *state, double loc, double scale) nogil
+ double rk_standard_exponential(rk_state *state) nogil
+ double rk_exponential(rk_state *state, double scale) nogil
+ double rk_uniform(rk_state *state, double loc, double scale) nogil
+ double rk_standard_gamma(rk_state *state, double shape) nogil
+ double rk_gamma(rk_state *state, double shape, double scale) nogil
+ double rk_beta(rk_state *state, double a, double b) nogil
+ double rk_chisquare(rk_state *state, double df) nogil
+ double rk_noncentral_chisquare(rk_state *state, double df, double nonc) nogil
+ double rk_f(rk_state *state, double dfnum, double dfden) nogil
+ double rk_noncentral_f(rk_state *state, double dfnum, double dfden, double nonc) nogil
+ double rk_standard_cauchy(rk_state *state) nogil
+ double rk_standard_t(rk_state *state, double df) nogil
+ double rk_vonmises(rk_state *state, double mu, double kappa) nogil
+ double rk_pareto(rk_state *state, double a) nogil
+ double rk_weibull(rk_state *state, double a) nogil
+ double rk_power(rk_state *state, double a) nogil
+ double rk_laplace(rk_state *state, double loc, double scale) nogil
+ double rk_gumbel(rk_state *state, double loc, double scale) nogil
+ double rk_logistic(rk_state *state, double loc, double scale) nogil
+ double rk_lognormal(rk_state *state, double mode, double sigma) nogil
+ double rk_rayleigh(rk_state *state, double mode) nogil
+ double rk_wald(rk_state *state, double mean, double scale) nogil
+ double rk_triangular(rk_state *state, double left, double mode, double right) nogil
+
+ long rk_binomial(rk_state *state, long n, double p) nogil
+ long rk_binomial_btpe(rk_state *state, long n, double p) nogil
+ long rk_binomial_inversion(rk_state *state, long n, double p) nogil
+ long rk_negative_binomial(rk_state *state, double n, double p) nogil
+ long rk_poisson(rk_state *state, double lam) nogil
+ long rk_poisson_mult(rk_state *state, double lam) nogil
+ long rk_poisson_ptrs(rk_state *state, double lam) nogil
+ long rk_zipf(rk_state *state, double a) nogil
+ long rk_geometric(rk_state *state, double p) nogil
+ long rk_hypergeometric(rk_state *state, long good, long bad, long sample) nogil
+ long rk_logseries(rk_state *state, double p) nogil
+
+ctypedef double (* rk_cont0)(rk_state *state) nogil
+ctypedef double (* rk_cont1)(rk_state *state, double a) nogil
+ctypedef double (* rk_cont2)(rk_state *state, double a, double b) nogil
+ctypedef double (* rk_cont3)(rk_state *state, double a, double b, double c) nogil
+
+ctypedef long (* rk_disc0)(rk_state *state) nogil
+ctypedef long (* rk_discnp)(rk_state *state, long n, double p) nogil
+ctypedef long (* rk_discdd)(rk_state *state, double n, double p) nogil
+ctypedef long (* rk_discnmN)(rk_state *state, long n, long m, long N) nogil
+ctypedef long (* rk_discd)(rk_state *state, double a) nogil
cdef extern from "initarray.h":
@@ -125,8 +126,11 @@ import_array()
import numpy as np
import operator
+import warnings
+from threading import Lock
-cdef object cont0_array(rk_state *state, rk_cont0 func, object size):
+cdef object cont0_array(rk_state *state, rk_cont0 func, object size,
+ object lock):
cdef double *array_data
cdef ndarray array "arrayObject"
cdef npy_intp length
@@ -138,12 +142,14 @@ cdef object cont0_array(rk_state *state, rk_cont0 func, object size):
array = <ndarray>np.empty(size, np.float64)
length = PyArray_SIZE(array)
array_data = <double *>PyArray_DATA(array)
- for i from 0 <= i < length:
- array_data[i] = func(state)
+ with lock, nogil:
+ for i from 0 <= i < length:
+ array_data[i] = func(state)
return array
-cdef object cont1_array_sc(rk_state *state, rk_cont1 func, object size, double a):
+cdef object cont1_array_sc(rk_state *state, rk_cont1 func, object size, double a,
+ object lock):
cdef double *array_data
cdef ndarray array "arrayObject"
cdef npy_intp length
@@ -155,11 +161,13 @@ cdef object cont1_array_sc(rk_state *state, rk_cont1 func, object size, double a
array = <ndarray>np.empty(size, np.float64)
length = PyArray_SIZE(array)
array_data = <double *>PyArray_DATA(array)
- for i from 0 <= i < length:
- array_data[i] = func(state, a)
+ with lock, nogil:
+ for i from 0 <= i < length:
+ array_data[i] = func(state, a)
return array
-cdef object cont1_array(rk_state *state, rk_cont1 func, object size, ndarray oa):
+cdef object cont1_array(rk_state *state, rk_cont1 func, object size,
+ ndarray oa, object lock):
cdef double *array_data
cdef double *oa_data
cdef ndarray array "arrayObject"
@@ -174,9 +182,10 @@ cdef object cont1_array(rk_state *state, rk_cont1 func, object size, ndarray oa)
length = PyArray_SIZE(array)
array_data = <double *>PyArray_DATA(array)
itera = <flatiter>PyArray_IterNew(<object>oa)
- for i from 0 <= i < length:
- array_data[i] = func(state, (<double *>(itera.dataptr))[0])
- PyArray_ITER_NEXT(itera)
+ with lock, nogil:
+ for i from 0 <= i < length:
+ array_data[i] = func(state, (<double *>(itera.dataptr))[0])
+ PyArray_ITER_NEXT(itera)
else:
array = <ndarray>np.empty(size, np.float64)
array_data = <double *>PyArray_DATA(array)
@@ -184,14 +193,15 @@ cdef object cont1_array(rk_state *state, rk_cont1 func, object size, ndarray oa)
<void *>oa)
if (multi.size != PyArray_SIZE(array)):
raise ValueError("size is not compatible with inputs")
- for i from 0 <= i < multi.size:
- oa_data = <double *>PyArray_MultiIter_DATA(multi, 1)
- array_data[i] = func(state, oa_data[0])
- PyArray_MultiIter_NEXTi(multi, 1)
+ with lock, nogil:
+ for i from 0 <= i < multi.size:
+ oa_data = <double *>PyArray_MultiIter_DATA(multi, 1)
+ array_data[i] = func(state, oa_data[0])
+ PyArray_MultiIter_NEXTi(multi, 1)
return array
cdef object cont2_array_sc(rk_state *state, rk_cont2 func, object size, double a,
- double b):
+ double b, object lock):
cdef double *array_data
cdef ndarray array "arrayObject"
cdef npy_intp length
@@ -203,13 +213,14 @@ cdef object cont2_array_sc(rk_state *state, rk_cont2 func, object size, double a
array = <ndarray>np.empty(size, np.float64)
length = PyArray_SIZE(array)
array_data = <double *>PyArray_DATA(array)
- for i from 0 <= i < length:
- array_data[i] = func(state, a, b)
+ with lock, nogil:
+ for i from 0 <= i < length:
+ array_data[i] = func(state, a, b)
return array
cdef object cont2_array(rk_state *state, rk_cont2 func, object size,
- ndarray oa, ndarray ob):
+ ndarray oa, ndarray ob, object lock):
cdef double *array_data
cdef double *oa_data
cdef double *ob_data
@@ -222,27 +233,29 @@ cdef object cont2_array(rk_state *state, rk_cont2 func, object size,
multi = <broadcast> PyArray_MultiIterNew(2, <void *>oa, <void *>ob)
array = <ndarray> PyArray_SimpleNew(multi.nd, multi.dimensions, NPY_DOUBLE)
array_data = <double *>PyArray_DATA(array)
- for i from 0 <= i < multi.size:
- oa_data = <double *>PyArray_MultiIter_DATA(multi, 0)
- ob_data = <double *>PyArray_MultiIter_DATA(multi, 1)
- array_data[i] = func(state, oa_data[0], ob_data[0])
- PyArray_MultiIter_NEXT(multi)
+ with lock, nogil:
+ for i from 0 <= i < multi.size:
+ oa_data = <double *>PyArray_MultiIter_DATA(multi, 0)
+ ob_data = <double *>PyArray_MultiIter_DATA(multi, 1)
+ array_data[i] = func(state, oa_data[0], ob_data[0])
+ PyArray_MultiIter_NEXT(multi)
else:
array = <ndarray>np.empty(size, np.float64)
array_data = <double *>PyArray_DATA(array)
multi = <broadcast>PyArray_MultiIterNew(3, <void*>array, <void *>oa, <void *>ob)
if (multi.size != PyArray_SIZE(array)):
raise ValueError("size is not compatible with inputs")
- for i from 0 <= i < multi.size:
- oa_data = <double *>PyArray_MultiIter_DATA(multi, 1)
- ob_data = <double *>PyArray_MultiIter_DATA(multi, 2)
- array_data[i] = func(state, oa_data[0], ob_data[0])
- PyArray_MultiIter_NEXTi(multi, 1)
- PyArray_MultiIter_NEXTi(multi, 2)
+ with lock, nogil:
+ for i from 0 <= i < multi.size:
+ oa_data = <double *>PyArray_MultiIter_DATA(multi, 1)
+ ob_data = <double *>PyArray_MultiIter_DATA(multi, 2)
+ array_data[i] = func(state, oa_data[0], ob_data[0])
+ PyArray_MultiIter_NEXTi(multi, 1)
+ PyArray_MultiIter_NEXTi(multi, 2)
return array
cdef object cont3_array_sc(rk_state *state, rk_cont3 func, object size, double a,
- double b, double c):
+ double b, double c, object lock):
cdef double *array_data
cdef ndarray array "arrayObject"
@@ -255,12 +268,13 @@ cdef object cont3_array_sc(rk_state *state, rk_cont3 func, object size, double a
array = <ndarray>np.empty(size, np.float64)
length = PyArray_SIZE(array)
array_data = <double *>PyArray_DATA(array)
- for i from 0 <= i < length:
- array_data[i] = func(state, a, b, c)
+ with lock, nogil:
+ for i from 0 <= i < length:
+ array_data[i] = func(state, a, b, c)
return array
-cdef object cont3_array(rk_state *state, rk_cont3 func, object size, ndarray oa,
- ndarray ob, ndarray oc):
+cdef object cont3_array(rk_state *state, rk_cont3 func, object size,
+ ndarray oa, ndarray ob, ndarray oc, object lock):
cdef double *array_data
cdef double *oa_data
@@ -275,12 +289,13 @@ cdef object cont3_array(rk_state *state, rk_cont3 func, object size, ndarray oa,
multi = <broadcast> PyArray_MultiIterNew(3, <void *>oa, <void *>ob, <void *>oc)
array = <ndarray> PyArray_SimpleNew(multi.nd, multi.dimensions, NPY_DOUBLE)
array_data = <double *>PyArray_DATA(array)
- for i from 0 <= i < multi.size:
- oa_data = <double *>PyArray_MultiIter_DATA(multi, 0)
- ob_data = <double *>PyArray_MultiIter_DATA(multi, 1)
- oc_data = <double *>PyArray_MultiIter_DATA(multi, 2)
- array_data[i] = func(state, oa_data[0], ob_data[0], oc_data[0])
- PyArray_MultiIter_NEXT(multi)
+ with lock, nogil:
+ for i from 0 <= i < multi.size:
+ oa_data = <double *>PyArray_MultiIter_DATA(multi, 0)
+ ob_data = <double *>PyArray_MultiIter_DATA(multi, 1)
+ oc_data = <double *>PyArray_MultiIter_DATA(multi, 2)
+ array_data[i] = func(state, oa_data[0], ob_data[0], oc_data[0])
+ PyArray_MultiIter_NEXT(multi)
else:
array = <ndarray>np.empty(size, np.float64)
array_data = <double *>PyArray_DATA(array)
@@ -288,15 +303,16 @@ cdef object cont3_array(rk_state *state, rk_cont3 func, object size, ndarray oa,
<void *>ob, <void *>oc)
if (multi.size != PyArray_SIZE(array)):
raise ValueError("size is not compatible with inputs")
- for i from 0 <= i < multi.size:
- oa_data = <double *>PyArray_MultiIter_DATA(multi, 1)
- ob_data = <double *>PyArray_MultiIter_DATA(multi, 2)
- oc_data = <double *>PyArray_MultiIter_DATA(multi, 3)
- array_data[i] = func(state, oa_data[0], ob_data[0], oc_data[0])
- PyArray_MultiIter_NEXT(multi)
+ with lock, nogil:
+ for i from 0 <= i < multi.size:
+ oa_data = <double *>PyArray_MultiIter_DATA(multi, 1)
+ ob_data = <double *>PyArray_MultiIter_DATA(multi, 2)
+ oc_data = <double *>PyArray_MultiIter_DATA(multi, 3)
+ array_data[i] = func(state, oa_data[0], ob_data[0], oc_data[0])
+ PyArray_MultiIter_NEXT(multi)
return array
-cdef object disc0_array(rk_state *state, rk_disc0 func, object size):
+cdef object disc0_array(rk_state *state, rk_disc0 func, object size, object lock):
cdef long *array_data
cdef ndarray array "arrayObject"
cdef npy_intp length
@@ -308,11 +324,13 @@ cdef object disc0_array(rk_state *state, rk_disc0 func, object size):
array = <ndarray>np.empty(size, int)
length = PyArray_SIZE(array)
array_data = <long *>PyArray_DATA(array)
- for i from 0 <= i < length:
- array_data[i] = func(state)
+ with lock, nogil:
+ for i from 0 <= i < length:
+ array_data[i] = func(state)
return array
-cdef object discnp_array_sc(rk_state *state, rk_discnp func, object size, long n, double p):
+cdef object discnp_array_sc(rk_state *state, rk_discnp func, object size,
+ long n, double p, object lock):
cdef long *array_data
cdef ndarray array "arrayObject"
cdef npy_intp length
@@ -324,11 +342,13 @@ cdef object discnp_array_sc(rk_state *state, rk_discnp func, object size, long n
array = <ndarray>np.empty(size, int)
length = PyArray_SIZE(array)
array_data = <long *>PyArray_DATA(array)
- for i from 0 <= i < length:
- array_data[i] = func(state, n, p)
+ with lock, nogil:
+ for i from 0 <= i < length:
+ array_data[i] = func(state, n, p)
return array
-cdef object discnp_array(rk_state *state, rk_discnp func, object size, ndarray on, ndarray op):
+cdef object discnp_array(rk_state *state, rk_discnp func, object size,
+ ndarray on, ndarray op, object lock):
cdef long *array_data
cdef ndarray array "arrayObject"
cdef npy_intp length
@@ -341,27 +361,30 @@ cdef object discnp_array(rk_state *state, rk_discnp func, object size, ndarray o
multi = <broadcast> PyArray_MultiIterNew(2, <void *>on, <void *>op)
array = <ndarray> PyArray_SimpleNew(multi.nd, multi.dimensions, NPY_LONG)
array_data = <long *>PyArray_DATA(array)
- for i from 0 <= i < multi.size:
- on_data = <long *>PyArray_MultiIter_DATA(multi, 0)
- op_data = <double *>PyArray_MultiIter_DATA(multi, 1)
- array_data[i] = func(state, on_data[0], op_data[0])
- PyArray_MultiIter_NEXT(multi)
+ with lock, nogil:
+ for i from 0 <= i < multi.size:
+ on_data = <long *>PyArray_MultiIter_DATA(multi, 0)
+ op_data = <double *>PyArray_MultiIter_DATA(multi, 1)
+ array_data[i] = func(state, on_data[0], op_data[0])
+ PyArray_MultiIter_NEXT(multi)
else:
array = <ndarray>np.empty(size, int)
array_data = <long *>PyArray_DATA(array)
multi = <broadcast>PyArray_MultiIterNew(3, <void*>array, <void *>on, <void *>op)
if (multi.size != PyArray_SIZE(array)):
raise ValueError("size is not compatible with inputs")
- for i from 0 <= i < multi.size:
- on_data = <long *>PyArray_MultiIter_DATA(multi, 1)
- op_data = <double *>PyArray_MultiIter_DATA(multi, 2)
- array_data[i] = func(state, on_data[0], op_data[0])
- PyArray_MultiIter_NEXTi(multi, 1)
- PyArray_MultiIter_NEXTi(multi, 2)
+ with lock, nogil:
+ for i from 0 <= i < multi.size:
+ on_data = <long *>PyArray_MultiIter_DATA(multi, 1)
+ op_data = <double *>PyArray_MultiIter_DATA(multi, 2)
+ array_data[i] = func(state, on_data[0], op_data[0])
+ PyArray_MultiIter_NEXTi(multi, 1)
+ PyArray_MultiIter_NEXTi(multi, 2)
return array
-cdef object discdd_array_sc(rk_state *state, rk_discdd func, object size, double n, double p):
+cdef object discdd_array_sc(rk_state *state, rk_discdd func, object size,
+ double n, double p, object lock):
cdef long *array_data
cdef ndarray array "arrayObject"
cdef npy_intp length
@@ -373,11 +396,13 @@ cdef object discdd_array_sc(rk_state *state, rk_discdd func, object size, double
array = <ndarray>np.empty(size, int)
length = PyArray_SIZE(array)
array_data = <long *>PyArray_DATA(array)
- for i from 0 <= i < length:
- array_data[i] = func(state, n, p)
+ with lock, nogil:
+ for i from 0 <= i < length:
+ array_data[i] = func(state, n, p)
return array
-cdef object discdd_array(rk_state *state, rk_discdd func, object size, ndarray on, ndarray op):
+cdef object discdd_array(rk_state *state, rk_discdd func, object size,
+ ndarray on, ndarray op, object lock):
cdef long *array_data
cdef ndarray array "arrayObject"
cdef npy_intp length
@@ -390,28 +415,30 @@ cdef object discdd_array(rk_state *state, rk_discdd func, object size, ndarray o
multi = <broadcast> PyArray_MultiIterNew(2, <void *>on, <void *>op)
array = <ndarray> PyArray_SimpleNew(multi.nd, multi.dimensions, NPY_LONG)
array_data = <long *>PyArray_DATA(array)
- for i from 0 <= i < multi.size:
- on_data = <double *>PyArray_MultiIter_DATA(multi, 0)
- op_data = <double *>PyArray_MultiIter_DATA(multi, 1)
- array_data[i] = func(state, on_data[0], op_data[0])
- PyArray_MultiIter_NEXT(multi)
+ with lock, nogil:
+ for i from 0 <= i < multi.size:
+ on_data = <double *>PyArray_MultiIter_DATA(multi, 0)
+ op_data = <double *>PyArray_MultiIter_DATA(multi, 1)
+ array_data[i] = func(state, on_data[0], op_data[0])
+ PyArray_MultiIter_NEXT(multi)
else:
array = <ndarray>np.empty(size, int)
array_data = <long *>PyArray_DATA(array)
multi = <broadcast>PyArray_MultiIterNew(3, <void*>array, <void *>on, <void *>op)
if (multi.size != PyArray_SIZE(array)):
raise ValueError("size is not compatible with inputs")
- for i from 0 <= i < multi.size:
- on_data = <double *>PyArray_MultiIter_DATA(multi, 1)
- op_data = <double *>PyArray_MultiIter_DATA(multi, 2)
- array_data[i] = func(state, on_data[0], op_data[0])
- PyArray_MultiIter_NEXTi(multi, 1)
- PyArray_MultiIter_NEXTi(multi, 2)
+ with lock, nogil:
+ for i from 0 <= i < multi.size:
+ on_data = <double *>PyArray_MultiIter_DATA(multi, 1)
+ op_data = <double *>PyArray_MultiIter_DATA(multi, 2)
+ array_data[i] = func(state, on_data[0], op_data[0])
+ PyArray_MultiIter_NEXTi(multi, 1)
+ PyArray_MultiIter_NEXTi(multi, 2)
return array
cdef object discnmN_array_sc(rk_state *state, rk_discnmN func, object size,
- long n, long m, long N):
+ long n, long m, long N, object lock):
cdef long *array_data
cdef ndarray array "arrayObject"
cdef npy_intp length
@@ -423,12 +450,13 @@ cdef object discnmN_array_sc(rk_state *state, rk_discnmN func, object size,
array = <ndarray>np.empty(size, int)
length = PyArray_SIZE(array)
array_data = <long *>PyArray_DATA(array)
- for i from 0 <= i < length:
- array_data[i] = func(state, n, m, N)
+ with lock, nogil:
+ for i from 0 <= i < length:
+ array_data[i] = func(state, n, m, N)
return array
cdef object discnmN_array(rk_state *state, rk_discnmN func, object size,
- ndarray on, ndarray om, ndarray oN):
+ ndarray on, ndarray om, ndarray oN, object lock):
cdef long *array_data
cdef long *on_data
cdef long *om_data
@@ -442,12 +470,13 @@ cdef object discnmN_array(rk_state *state, rk_discnmN func, object size,
multi = <broadcast> PyArray_MultiIterNew(3, <void *>on, <void *>om, <void *>oN)
array = <ndarray> PyArray_SimpleNew(multi.nd, multi.dimensions, NPY_LONG)
array_data = <long *>PyArray_DATA(array)
- for i from 0 <= i < multi.size:
- on_data = <long *>PyArray_MultiIter_DATA(multi, 0)
- om_data = <long *>PyArray_MultiIter_DATA(multi, 1)
- oN_data = <long *>PyArray_MultiIter_DATA(multi, 2)
- array_data[i] = func(state, on_data[0], om_data[0], oN_data[0])
- PyArray_MultiIter_NEXT(multi)
+ with lock, nogil:
+ for i from 0 <= i < multi.size:
+ on_data = <long *>PyArray_MultiIter_DATA(multi, 0)
+ om_data = <long *>PyArray_MultiIter_DATA(multi, 1)
+ oN_data = <long *>PyArray_MultiIter_DATA(multi, 2)
+ array_data[i] = func(state, on_data[0], om_data[0], oN_data[0])
+ PyArray_MultiIter_NEXT(multi)
else:
array = <ndarray>np.empty(size, int)
array_data = <long *>PyArray_DATA(array)
@@ -455,16 +484,18 @@ cdef object discnmN_array(rk_state *state, rk_discnmN func, object size,
<void *>oN)
if (multi.size != PyArray_SIZE(array)):
raise ValueError("size is not compatible with inputs")
- for i from 0 <= i < multi.size:
- on_data = <long *>PyArray_MultiIter_DATA(multi, 1)
- om_data = <long *>PyArray_MultiIter_DATA(multi, 2)
- oN_data = <long *>PyArray_MultiIter_DATA(multi, 3)
- array_data[i] = func(state, on_data[0], om_data[0], oN_data[0])
- PyArray_MultiIter_NEXT(multi)
+ with lock, nogil:
+ for i from 0 <= i < multi.size:
+ on_data = <long *>PyArray_MultiIter_DATA(multi, 1)
+ om_data = <long *>PyArray_MultiIter_DATA(multi, 2)
+ oN_data = <long *>PyArray_MultiIter_DATA(multi, 3)
+ array_data[i] = func(state, on_data[0], om_data[0], oN_data[0])
+ PyArray_MultiIter_NEXT(multi)
return array
-cdef object discd_array_sc(rk_state *state, rk_discd func, object size, double a):
+cdef object discd_array_sc(rk_state *state, rk_discd func, object size,
+ double a, object lock):
cdef long *array_data
cdef ndarray array "arrayObject"
cdef npy_intp length
@@ -476,11 +507,13 @@ cdef object discd_array_sc(rk_state *state, rk_discd func, object size, double a
array = <ndarray>np.empty(size, int)
length = PyArray_SIZE(array)
array_data = <long *>PyArray_DATA(array)
- for i from 0 <= i < length:
- array_data[i] = func(state, a)
+ with lock, nogil:
+ for i from 0 <= i < length:
+ array_data[i] = func(state, a)
return array
-cdef object discd_array(rk_state *state, rk_discd func, object size, ndarray oa):
+cdef object discd_array(rk_state *state, rk_discd func, object size, ndarray oa,
+ object lock):
cdef long *array_data
cdef double *oa_data
cdef ndarray array "arrayObject"
@@ -495,19 +528,21 @@ cdef object discd_array(rk_state *state, rk_discd func, object size, ndarray oa)
length = PyArray_SIZE(array)
array_data = <long *>PyArray_DATA(array)
itera = <flatiter>PyArray_IterNew(<object>oa)
- for i from 0 <= i < length:
- array_data[i] = func(state, (<double *>(itera.dataptr))[0])
- PyArray_ITER_NEXT(itera)
+ with lock, nogil:
+ for i from 0 <= i < length:
+ array_data[i] = func(state, (<double *>(itera.dataptr))[0])
+ PyArray_ITER_NEXT(itera)
else:
array = <ndarray>np.empty(size, int)
array_data = <long *>PyArray_DATA(array)
multi = <broadcast>PyArray_MultiIterNew(2, <void *>array, <void *>oa)
if (multi.size != PyArray_SIZE(array)):
raise ValueError("size is not compatible with inputs")
- for i from 0 <= i < multi.size:
- oa_data = <double *>PyArray_MultiIter_DATA(multi, 1)
- array_data[i] = func(state, oa_data[0])
- PyArray_MultiIter_NEXTi(multi, 1)
+ with lock, nogil:
+ for i from 0 <= i < multi.size:
+ oa_data = <double *>PyArray_MultiIter_DATA(multi, 1)
+ array_data[i] = func(state, oa_data[0])
+ PyArray_MultiIter_NEXTi(multi, 1)
return array
cdef double kahan_sum(double *darr, npy_intp n):
@@ -522,6 +557,16 @@ cdef double kahan_sum(double *darr, npy_intp n):
sum = t
return sum
+def _shape_from_size(size, d):
+ if size is None:
+ shape = (d,)
+ else:
+ try:
+ shape = (operator.index(size), d)
+ except TypeError:
+ shape = tuple(size) + (d,)
+ return shape
+
cdef class RandomState:
"""
RandomState(seed=None)
@@ -556,12 +601,14 @@ cdef class RandomState:
"""
cdef rk_state *internal_state
+ cdef object lock
poisson_lam_max = np.iinfo('l').max - np.sqrt(np.iinfo('l').max)*10
def __init__(self, seed=None):
self.internal_state = <rk_state*>PyMem_Malloc(sizeof(rk_state))
self.seed(seed)
+ self.lock = Lock()
def __dealloc__(self):
if self.internal_state != NULL:
@@ -581,6 +628,7 @@ cdef class RandomState:
----------
seed : int or array_like, optional
Seed for `RandomState`.
+ Must be convertable to 32 bit unsigned integers.
See Also
--------
@@ -589,15 +637,19 @@ cdef class RandomState:
"""
cdef rk_error errcode
cdef ndarray obj "arrayObject_obj"
- if seed is None:
- errcode = rk_randomseed(self.internal_state)
- elif type(seed) is int:
- rk_seed(seed, self.internal_state)
- elif isinstance(seed, np.integer):
- iseed = int(seed)
- rk_seed(iseed, self.internal_state)
- else:
- obj = <ndarray>PyArray_ContiguousFromObject(seed, NPY_LONG, 1, 1)
+ try:
+ if seed is None:
+ errcode = rk_randomseed(self.internal_state)
+ else:
+ idx = operator.index(seed)
+ if idx > int(2**32 - 1) or idx < 0:
+ raise ValueError("Seed must be between 0 and 4294967295")
+ rk_seed(idx, self.internal_state)
+ except TypeError:
+ obj = np.asarray(seed).astype(np.int64, casting='safe')
+ if ((obj > int(2**32 - 1)) | (obj < 0)).any():
+ raise ValueError("Seed must be between 0 and 4294967295")
+ obj = obj.astype('L', casting='unsafe')
init_by_array(self.internal_state, <unsigned long *>PyArray_DATA(obj),
PyArray_DIM(obj, 0))
@@ -734,8 +786,9 @@ cdef class RandomState:
Parameters
----------
size : int or tuple of ints, optional
- Defines the shape of the returned array of random floats. If None
- (the default), returns a single float.
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -760,7 +813,7 @@ cdef class RandomState:
[-1.23204345, -1.75224494]])
"""
- return cont0_array(self.internal_state, rk_double, size)
+ return cont0_array(self.internal_state, rk_double, size, self.lock)
def tomaxint(self, size=None):
"""
@@ -773,10 +826,10 @@ cdef class RandomState:
Parameters
----------
- size : tuple of ints, int, optional
- Shape of output. If this is, for example, (m,n,k), m*n*k samples
- are generated. If no shape is specified, a single sample is
- returned.
+ 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. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -807,7 +860,7 @@ cdef class RandomState:
[ True, True]]], dtype=bool)
"""
- return disc0_array(self.internal_state, rk_long, size)
+ return disc0_array(self.internal_state, rk_long, size, self.lock)
def randint(self, low, high=None, size=None):
"""
@@ -829,8 +882,9 @@ cdef class RandomState:
If provided, one above the largest (signed) integer to be drawn
from the distribution (see above for behavior if ``high=None``).
size : int or tuple of ints, optional
- Output shape. Default is None, in which case a single int is
- returned.
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -884,9 +938,10 @@ cdef class RandomState:
array = <ndarray>np.empty(size, int)
length = PyArray_SIZE(array)
array_data = <long *>PyArray_DATA(array)
- for i from 0 <= i < length:
- rv = lo + <long>rk_interval(diff, self. internal_state)
- array_data[i] = rv
+ with self.lock, nogil:
+ for i from 0 <= i < length:
+ rv = lo + <long>rk_interval(diff, self. internal_state)
+ array_data[i] = rv
return array
def bytes(self, npy_intp length):
@@ -913,7 +968,8 @@ cdef class RandomState:
"""
cdef void *bytes
bytestring = empty_py_bytes(length, &bytes)
- rk_fill(bytes, length, self.internal_state)
+ with self.lock, nogil:
+ rk_fill(bytes, length, self.internal_state)
return bytestring
@@ -931,13 +987,14 @@ cdef class RandomState:
If an ndarray, a random sample is generated from its elements.
If an int, the random sample is generated as if a was np.arange(n)
size : int or tuple of ints, optional
- Output shape. Default is None, in which case a single value is
- returned.
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
replace : boolean, optional
Whether the sample is with or without replacement
p : 1-D array-like, optional
The probabilities associated with each entry in a.
- If not given the sample assumes a uniform distribtion over all
+ If not given the sample assumes a uniform distribution over all
entries in a.
Returns
@@ -976,7 +1033,7 @@ cdef class RandomState:
>>> np.random.choice(5, 3, replace=False)
array([3,1,0])
- >>> #This is equivalent to np.random.shuffle(np.arange(5))[:3]
+ >>> #This is equivalent to np.random.permutation(np.arange(5))[:3]
Generate a non-uniform random sample from np.arange(5) of size
3 without replacement:
@@ -1012,14 +1069,17 @@ cdef class RandomState:
raise ValueError("a must be non-empty")
if None != p:
- p = np.array(p, dtype=np.double, ndmin=1, copy=False)
+ d = len(p)
+ p = <ndarray>PyArray_ContiguousFromObject(p, NPY_DOUBLE, 1, 1)
+ pix = <double*>PyArray_DATA(p)
+
if p.ndim != 1:
raise ValueError("p must be 1-dimensional")
if p.size != pop_size:
raise ValueError("a and p must have same size")
- if np.any(p < 0):
+ if np.logical_or.reduce(p < 0):
raise ValueError("probabilities are not non-negative")
- if not np.allclose(p.sum(), 1):
+ if abs(kahan_sum(pix, d) - 1.) > 1e-8:
raise ValueError("probabilities do not sum to 1")
shape = size
@@ -1044,7 +1104,7 @@ cdef class RandomState:
"population when 'replace=False'")
if None != p:
- if np.sum(p > 0) < size:
+ if np.count_nonzero(p > 0) < size:
raise ValueError("Fewer non-zero entries in p than size")
n_uniq = 0
p = p.copy()
@@ -1091,7 +1151,7 @@ cdef class RandomState:
def uniform(self, low=0.0, high=1.0, size=None):
"""
- uniform(low=0.0, high=1.0, size=1)
+ uniform(low=0.0, high=1.0, size=None)
Draw samples from a uniform distribution.
@@ -1109,9 +1169,9 @@ cdef class RandomState:
Upper boundary of the output interval. All values generated will be
less than high. The default value is 1.0.
size : int or tuple of ints, optional
- Shape of output. If the given size is, for example, (m,n,k),
- m*n*k samples are generated. If no shape is specified, a single sample
- is returned.
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -1166,7 +1226,9 @@ cdef class RandomState:
flow = PyFloat_AsDouble(low)
fhigh = PyFloat_AsDouble(high)
if not PyErr_Occurred():
- return cont2_array_sc(self.internal_state, rk_uniform, size, flow, fhigh-flow)
+ return cont2_array_sc(self.internal_state, rk_uniform, size, flow,
+ fhigh-flow, self.lock)
+
PyErr_Clear()
olow = <ndarray>PyArray_FROM_OTF(low, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
ohigh = <ndarray>PyArray_FROM_OTF(high, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
@@ -1174,7 +1236,8 @@ cdef class RandomState:
Py_INCREF(temp) # needed to get around Pyrex's automatic reference-counting
# rules because EnsureArray steals a reference
odiff = <ndarray>PyArray_EnsureArray(temp)
- return cont2_array(self.internal_state, rk_uniform, size, olow, odiff)
+ return cont2_array(self.internal_state, rk_uniform, size, olow, odiff,
+ self.lock)
def rand(self, *args):
"""
@@ -1297,7 +1360,9 @@ cdef class RandomState:
If provided, the largest (signed) integer to be drawn from the
distribution (see above for behavior if ``high=None``).
size : int or tuple of ints, optional
- Output shape. Default is None, in which case a single int is returned.
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -1364,8 +1429,9 @@ cdef class RandomState:
Parameters
----------
size : int or tuple of ints, optional
- Output shape. Default is None, in which case a single value is
- returned.
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -1385,7 +1451,7 @@ cdef class RandomState:
(3, 4, 2)
"""
- return cont0_array(self.internal_state, rk_gauss, size)
+ return cont0_array(self.internal_state, rk_gauss, size, self.lock)
def normal(self, loc=0.0, scale=1.0, size=None):
"""
@@ -1409,9 +1475,10 @@ cdef class RandomState:
Mean ("centre") of the distribution.
scale : float
Standard deviation (spread or "width") of the distribution.
- size : tuple of ints
+ 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.
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
See Also
--------
@@ -1477,7 +1544,8 @@ cdef class RandomState:
if not PyErr_Occurred():
if fscale <= 0:
raise ValueError("scale <= 0")
- return cont2_array_sc(self.internal_state, rk_normal, size, floc, fscale)
+ return cont2_array_sc(self.internal_state, rk_normal, size, floc,
+ fscale, self.lock)
PyErr_Clear()
@@ -1485,7 +1553,8 @@ cdef class RandomState:
oscale = <ndarray>PyArray_FROM_OTF(scale, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
if np.any(np.less_equal(oscale, 0)):
raise ValueError("scale <= 0")
- return cont2_array(self.internal_state, rk_normal, size, oloc, oscale)
+ return cont2_array(self.internal_state, rk_normal, size, oloc, oscale,
+ self.lock)
def beta(self, a, b, size=None):
"""
@@ -1513,9 +1582,10 @@ cdef class RandomState:
Alpha, non-negative.
b : float
Beta, non-negative.
- size : tuple of ints, optional
- The number of samples to draw. The output is packed according to
- the size given.
+ 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. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -1534,7 +1604,8 @@ cdef class RandomState:
raise ValueError("a <= 0")
if fb <= 0:
raise ValueError("b <= 0")
- return cont2_array_sc(self.internal_state, rk_beta, size, fa, fb)
+ return cont2_array_sc(self.internal_state, rk_beta, size, fa, fb,
+ self.lock)
PyErr_Clear()
@@ -1544,7 +1615,8 @@ cdef class RandomState:
raise ValueError("a <= 0")
if np.any(np.less_equal(ob, 0)):
raise ValueError("b <= 0")
- return cont2_array(self.internal_state, rk_beta, size, oa, ob)
+ return cont2_array(self.internal_state, rk_beta, size, oa, ob,
+ self.lock)
def exponential(self, scale=1.0, size=None):
"""
@@ -1570,9 +1642,10 @@ cdef class RandomState:
----------
scale : float
The scale parameter, :math:`\\beta = 1/\\lambda`.
- size : tuple of ints
- Number of samples to draw. The output is shaped
- according to `size`.
+ 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. Default is None, in which case a
+ single value is returned.
References
----------
@@ -1591,14 +1664,16 @@ cdef class RandomState:
if not PyErr_Occurred():
if fscale <= 0:
raise ValueError("scale <= 0")
- return cont1_array_sc(self.internal_state, rk_exponential, size, fscale)
+ return cont1_array_sc(self.internal_state, rk_exponential, size,
+ fscale, self.lock)
PyErr_Clear()
oscale = <ndarray> PyArray_FROM_OTF(scale, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
if np.any(np.less_equal(oscale, 0.0)):
raise ValueError("scale <= 0")
- return cont1_array(self.internal_state, rk_exponential, size, oscale)
+ return cont1_array(self.internal_state, rk_exponential, size, oscale,
+ self.lock)
def standard_exponential(self, size=None):
"""
@@ -1611,8 +1686,10 @@ cdef class RandomState:
Parameters
----------
- size : int or tuple of ints
- Shape of the output.
+ 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. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -1626,7 +1703,8 @@ cdef class RandomState:
>>> n = np.random.standard_exponential((3, 8000))
"""
- return cont0_array(self.internal_state, rk_standard_exponential, size)
+ return cont0_array(self.internal_state, rk_standard_exponential, size,
+ self.lock)
def standard_gamma(self, shape, size=None):
"""
@@ -1641,9 +1719,10 @@ cdef class RandomState:
----------
shape : float
Parameter, should be > 0.
- size : int or tuple of ints
+ 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.
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -1702,13 +1781,14 @@ cdef class RandomState:
if not PyErr_Occurred():
if fshape <= 0:
raise ValueError("shape <= 0")
- return cont1_array_sc(self.internal_state, rk_standard_gamma, size, fshape)
+ return cont1_array_sc(self.internal_state, rk_standard_gamma, size, fshape, self.lock)
PyErr_Clear()
oshape = <ndarray> PyArray_FROM_OTF(shape, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
if np.any(np.less_equal(oshape, 0.0)):
raise ValueError("shape <= 0")
- return cont1_array(self.internal_state, rk_standard_gamma, size, oshape)
+ return cont1_array(self.internal_state, rk_standard_gamma, size,
+ oshape, self.lock)
def gamma(self, shape, scale=1.0, size=None):
"""
@@ -1726,9 +1806,10 @@ cdef class RandomState:
The shape of the gamma distribution.
scale : scalar > 0, optional
The scale of the gamma distribution. Default is equal to 1.
- size : shape_tuple, optional
+ 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.
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -1790,7 +1871,8 @@ cdef class RandomState:
raise ValueError("shape <= 0")
if fscale <= 0:
raise ValueError("scale <= 0")
- return cont2_array_sc(self.internal_state, rk_gamma, size, fshape, fscale)
+ return cont2_array_sc(self.internal_state, rk_gamma, size, fshape,
+ fscale, self.lock)
PyErr_Clear()
oshape = <ndarray>PyArray_FROM_OTF(shape, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
@@ -1799,7 +1881,8 @@ cdef class RandomState:
raise ValueError("shape <= 0")
if np.any(np.less_equal(oscale, 0.0)):
raise ValueError("scale <= 0")
- return cont2_array(self.internal_state, rk_gamma, size, oshape, oscale)
+ return cont2_array(self.internal_state, rk_gamma, size, oshape, oscale,
+ self.lock)
def f(self, dfnum, dfden, size=None):
"""
@@ -1822,10 +1905,10 @@ cdef class RandomState:
Degrees of freedom in numerator. Should be greater than zero.
dfden : float
Degrees of freedom in denominator. Should be greater than zero.
- size : {tuple, int}, optional
- Output shape. If the given shape is, e.g., ``(m, n, k)``,
- then ``m * n * k`` samples are drawn. By default only one sample
- is returned.
+ 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. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -1891,7 +1974,8 @@ cdef class RandomState:
raise ValueError("shape <= 0")
if fdfden <= 0:
raise ValueError("scale <= 0")
- return cont2_array_sc(self.internal_state, rk_f, size, fdfnum, fdfden)
+ return cont2_array_sc(self.internal_state, rk_f, size, fdfnum,
+ fdfden, self.lock)
PyErr_Clear()
@@ -1901,7 +1985,8 @@ cdef class RandomState:
raise ValueError("dfnum <= 0")
if np.any(np.less_equal(odfden, 0.0)):
raise ValueError("dfden <= 0")
- return cont2_array(self.internal_state, rk_f, size, odfnum, odfden)
+ return cont2_array(self.internal_state, rk_f, size, odfnum, odfden,
+ self.lock)
def noncentral_f(self, dfnum, dfden, nonc, size=None):
"""
@@ -1922,9 +2007,10 @@ cdef class RandomState:
Parameter, should be > 1.
nonc : float
Parameter, should be >= 0.
- size : int or tuple of ints
- Output shape. If the given shape is, e.g., ``(m, n, k)``, then
- ``m * n * k`` samples are drawn.
+ 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. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -1981,7 +2067,7 @@ cdef class RandomState:
if fnonc < 0:
raise ValueError("nonc < 0")
return cont3_array_sc(self.internal_state, rk_noncentral_f, size,
- fdfnum, fdfden, fnonc)
+ fdfnum, fdfden, fnonc, self.lock)
PyErr_Clear()
@@ -1996,7 +2082,7 @@ cdef class RandomState:
if np.any(np.less(ononc, 0.0)):
raise ValueError("nonc < 0")
return cont3_array(self.internal_state, rk_noncentral_f, size, odfnum,
- odfden, ononc)
+ odfden, ononc, self.lock)
def chisquare(self, df, size=None):
"""
@@ -2013,9 +2099,10 @@ cdef class RandomState:
----------
df : int
Number of degrees of freedom.
- size : tuple of ints, int, optional
- Size of the returned array. By default, a scalar is
- returned.
+ 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. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -2067,14 +2154,16 @@ cdef class RandomState:
if not PyErr_Occurred():
if fdf <= 0:
raise ValueError("df <= 0")
- return cont1_array_sc(self.internal_state, rk_chisquare, size, fdf)
+ return cont1_array_sc(self.internal_state, rk_chisquare, size, fdf,
+ self.lock)
PyErr_Clear()
odf = <ndarray>PyArray_FROM_OTF(df, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
if np.any(np.less_equal(odf, 0.0)):
raise ValueError("df <= 0")
- return cont1_array(self.internal_state, rk_chisquare, size, odf)
+ return cont1_array(self.internal_state, rk_chisquare, size, odf,
+ self.lock)
def noncentral_chisquare(self, df, nonc, size=None):
"""
@@ -2091,8 +2180,10 @@ cdef class RandomState:
Degrees of freedom, should be >= 1.
nonc : float
Non-centrality, should be > 0.
- size : int or tuple of ints
- Shape of the output.
+ 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. Default is None, in which case a
+ single value is returned.
Notes
-----
@@ -2155,7 +2246,7 @@ cdef class RandomState:
if fnonc <= 0:
raise ValueError("nonc <= 0")
return cont2_array_sc(self.internal_state, rk_noncentral_chisquare,
- size, fdf, fnonc)
+ size, fdf, fnonc, self.lock)
PyErr_Clear()
@@ -2166,7 +2257,7 @@ cdef class RandomState:
if np.any(np.less_equal(ononc, 0.0)):
raise ValueError("nonc < 0")
return cont2_array(self.internal_state, rk_noncentral_chisquare, size,
- odf, ononc)
+ odf, ononc, self.lock)
def standard_cauchy(self, size=None):
"""
@@ -2178,8 +2269,10 @@ cdef class RandomState:
Parameters
----------
- size : int or tuple of ints
- Shape of the output.
+ 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. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -2227,7 +2320,8 @@ cdef class RandomState:
>>> plt.show()
"""
- return cont0_array(self.internal_state, rk_standard_cauchy, size)
+ return cont0_array(self.internal_state, rk_standard_cauchy, size,
+ self.lock)
def standard_t(self, df, size=None):
"""
@@ -2244,8 +2338,9 @@ cdef class RandomState:
df : int
Degrees of freedom, should be > 0.
size : int or tuple of ints, optional
- Output shape. Default is None, in which case a single value is
- returned.
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -2321,14 +2416,16 @@ cdef class RandomState:
if not PyErr_Occurred():
if fdf <= 0:
raise ValueError("df <= 0")
- return cont1_array_sc(self.internal_state, rk_standard_t, size, fdf)
+ return cont1_array_sc(self.internal_state, rk_standard_t, size,
+ fdf, self.lock)
PyErr_Clear()
odf = <ndarray> PyArray_FROM_OTF(df, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
if np.any(np.less_equal(odf, 0.0)):
raise ValueError("df <= 0")
- return cont1_array(self.internal_state, rk_standard_t, size, odf)
+ return cont1_array(self.internal_state, rk_standard_t, size, odf,
+ self.lock)
def vonmises(self, mu, kappa, size=None):
"""
@@ -2350,9 +2447,10 @@ cdef class RandomState:
Mode ("center") of the distribution.
kappa : float
Dispersion of the distribution, has to be >=0.
- size : int or tuple of int
+ 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.
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -2414,7 +2512,8 @@ cdef class RandomState:
if not PyErr_Occurred():
if fkappa < 0:
raise ValueError("kappa < 0")
- return cont2_array_sc(self.internal_state, rk_vonmises, size, fmu, fkappa)
+ return cont2_array_sc(self.internal_state, rk_vonmises, size, fmu,
+ fkappa, self.lock)
PyErr_Clear()
@@ -2422,7 +2521,8 @@ cdef class RandomState:
okappa = <ndarray> PyArray_FROM_OTF(kappa, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
if np.any(np.less(okappa, 0.0)):
raise ValueError("kappa < 0")
- return cont2_array(self.internal_state, rk_vonmises, size, omu, okappa)
+ return cont2_array(self.internal_state, rk_vonmises, size, omu, okappa,
+ self.lock)
def pareto(self, a, size=None):
"""
@@ -2448,9 +2548,10 @@ cdef class RandomState:
----------
shape : float, > 0.
Shape of the distribution.
- size : tuple of ints
+ 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.
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
See Also
--------
@@ -2511,14 +2612,15 @@ cdef class RandomState:
if not PyErr_Occurred():
if fa <= 0:
raise ValueError("a <= 0")
- return cont1_array_sc(self.internal_state, rk_pareto, size, fa)
+ return cont1_array_sc(self.internal_state, rk_pareto, size, fa,
+ self.lock)
PyErr_Clear()
oa = <ndarray>PyArray_FROM_OTF(a, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
if np.any(np.less_equal(oa, 0.0)):
raise ValueError("a <= 0")
- return cont1_array(self.internal_state, rk_pareto, size, oa)
+ return cont1_array(self.internal_state, rk_pareto, size, oa, self.lock)
def weibull(self, a, size=None):
"""
@@ -2540,9 +2642,10 @@ cdef class RandomState:
----------
a : float
Shape of the distribution.
- size : tuple of ints
+ 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.
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
See Also
--------
@@ -2611,14 +2714,16 @@ cdef class RandomState:
if not PyErr_Occurred():
if fa <= 0:
raise ValueError("a <= 0")
- return cont1_array_sc(self.internal_state, rk_weibull, size, fa)
+ return cont1_array_sc(self.internal_state, rk_weibull, size, fa,
+ self.lock)
PyErr_Clear()
oa = <ndarray>PyArray_FROM_OTF(a, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
if np.any(np.less_equal(oa, 0.0)):
raise ValueError("a <= 0")
- return cont1_array(self.internal_state, rk_weibull, size, oa)
+ return cont1_array(self.internal_state, rk_weibull, size, oa,
+ self.lock)
def power(self, a, size=None):
"""
@@ -2633,9 +2738,10 @@ cdef class RandomState:
----------
a : float
parameter, > 0
- size : tuple of ints
+ 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.
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -2720,14 +2826,15 @@ cdef class RandomState:
if not PyErr_Occurred():
if fa <= 0:
raise ValueError("a <= 0")
- return cont1_array_sc(self.internal_state, rk_power, size, fa)
+ return cont1_array_sc(self.internal_state, rk_power, size, fa,
+ self.lock)
PyErr_Clear()
oa = <ndarray>PyArray_FROM_OTF(a, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
if np.any(np.less_equal(oa, 0.0)):
raise ValueError("a <= 0")
- return cont1_array(self.internal_state, rk_power, size, oa)
+ return cont1_array(self.internal_state, rk_power, size, oa, self.lock)
def laplace(self, loc=0.0, scale=1.0, size=None):
"""
@@ -2747,6 +2854,10 @@ cdef class RandomState:
The position, :math:`\\mu`, of the distribution peak.
scale : float
:math:`\\lambda`, the exponential decay.
+ 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. Default is None, in which case a
+ single value is returned.
Notes
-----
@@ -2810,14 +2921,16 @@ cdef class RandomState:
if not PyErr_Occurred():
if fscale <= 0:
raise ValueError("scale <= 0")
- return cont2_array_sc(self.internal_state, rk_laplace, size, floc, fscale)
+ return cont2_array_sc(self.internal_state, rk_laplace, size, floc,
+ fscale, self.lock)
PyErr_Clear()
oloc = PyArray_FROM_OTF(loc, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
oscale = PyArray_FROM_OTF(scale, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
if np.any(np.less_equal(oscale, 0.0)):
raise ValueError("scale <= 0")
- return cont2_array(self.internal_state, rk_laplace, size, oloc, oscale)
+ return cont2_array(self.internal_state, rk_laplace, size, oloc, oscale,
+ self.lock)
def gumbel(self, loc=0.0, scale=1.0, size=None):
"""
@@ -2835,9 +2948,10 @@ cdef class RandomState:
The location of the mode of the distribution.
scale : float
The scale parameter of the distribution.
- size : tuple of ints
+ 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.
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -2941,14 +3055,16 @@ cdef class RandomState:
if not PyErr_Occurred():
if fscale <= 0:
raise ValueError("scale <= 0")
- return cont2_array_sc(self.internal_state, rk_gumbel, size, floc, fscale)
+ return cont2_array_sc(self.internal_state, rk_gumbel, size, floc,
+ fscale, self.lock)
PyErr_Clear()
oloc = PyArray_FROM_OTF(loc, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
oscale = PyArray_FROM_OTF(scale, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
if np.any(np.less_equal(oscale, 0.0)):
raise ValueError("scale <= 0")
- return cont2_array(self.internal_state, rk_gumbel, size, oloc, oscale)
+ return cont2_array(self.internal_state, rk_gumbel, size, oloc, oscale,
+ self.lock)
def logistic(self, loc=0.0, scale=1.0, size=None):
"""
@@ -2965,9 +3081,10 @@ cdef class RandomState:
scale : float > 0.
- size : {tuple, int}
+ 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.
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -3029,14 +3146,16 @@ cdef class RandomState:
if not PyErr_Occurred():
if fscale <= 0:
raise ValueError("scale <= 0")
- return cont2_array_sc(self.internal_state, rk_logistic, size, floc, fscale)
+ return cont2_array_sc(self.internal_state, rk_logistic, size, floc,
+ fscale, self.lock)
PyErr_Clear()
oloc = PyArray_FROM_OTF(loc, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
oscale = PyArray_FROM_OTF(scale, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
if np.any(np.less_equal(oscale, 0.0)):
raise ValueError("scale <= 0")
- return cont2_array(self.internal_state, rk_logistic, size, oloc, oscale)
+ return cont2_array(self.internal_state, rk_logistic, size, oloc,
+ oscale, self.lock)
def lognormal(self, mean=0.0, sigma=1.0, size=None):
"""
@@ -3055,9 +3174,10 @@ cdef class RandomState:
Mean value of the underlying normal distribution
sigma : float, > 0.
Standard deviation of the underlying normal distribution
- size : tuple of ints
+ 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.
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -3149,7 +3269,8 @@ cdef class RandomState:
if not PyErr_Occurred():
if fsigma <= 0:
raise ValueError("sigma <= 0")
- return cont2_array_sc(self.internal_state, rk_lognormal, size, fmean, fsigma)
+ return cont2_array_sc(self.internal_state, rk_lognormal, size,
+ fmean, fsigma, self.lock)
PyErr_Clear()
@@ -3157,7 +3278,8 @@ cdef class RandomState:
osigma = PyArray_FROM_OTF(sigma, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
if np.any(np.less_equal(osigma, 0.0)):
raise ValueError("sigma <= 0.0")
- return cont2_array(self.internal_state, rk_lognormal, size, omean, osigma)
+ return cont2_array(self.internal_state, rk_lognormal, size, omean,
+ osigma, self.lock)
def rayleigh(self, scale=1.0, size=None):
"""
@@ -3173,8 +3295,9 @@ cdef class RandomState:
scale : scalar
Scale, also equals the mode. Should be >= 0.
size : int or tuple of ints, optional
- Shape of the output. Default is None, in which case a single
- value is returned.
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
Notes
-----
@@ -3222,14 +3345,16 @@ cdef class RandomState:
if not PyErr_Occurred():
if fscale <= 0:
raise ValueError("scale <= 0")
- return cont1_array_sc(self.internal_state, rk_rayleigh, size, fscale)
+ return cont1_array_sc(self.internal_state, rk_rayleigh, size,
+ fscale, self.lock)
PyErr_Clear()
oscale = <ndarray>PyArray_FROM_OTF(scale, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
if np.any(np.less_equal(oscale, 0.0)):
raise ValueError("scale <= 0.0")
- return cont1_array(self.internal_state, rk_rayleigh, size, oscale)
+ return cont1_array(self.internal_state, rk_rayleigh, size, oscale,
+ self.lock)
def wald(self, mean, scale, size=None):
"""
@@ -3255,8 +3380,9 @@ cdef class RandomState:
scale : scalar
Scale parameter, should be >= 0.
size : int or tuple of ints, optional
- Output shape. Default is None, in which case a single value is
- returned.
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -3304,7 +3430,8 @@ cdef class RandomState:
raise ValueError("mean <= 0")
if fscale <= 0:
raise ValueError("scale <= 0")
- return cont2_array_sc(self.internal_state, rk_wald, size, fmean, fscale)
+ return cont2_array_sc(self.internal_state, rk_wald, size, fmean,
+ fscale, self.lock)
PyErr_Clear()
omean = PyArray_FROM_OTF(mean, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
@@ -3313,9 +3440,8 @@ cdef class RandomState:
raise ValueError("mean <= 0.0")
elif np.any(np.less_equal(oscale,0.0)):
raise ValueError("scale <= 0.0")
- return cont2_array(self.internal_state, rk_wald, size, omean, oscale)
-
-
+ return cont2_array(self.internal_state, rk_wald, size, omean, oscale,
+ self.lock)
def triangular(self, left, mode, right, size=None):
"""
@@ -3337,8 +3463,9 @@ cdef class RandomState:
right : scalar
Upper limit, should be larger than `left`.
size : int or tuple of ints, optional
- Output shape. Default is None, in which case a single value is
- returned.
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -3388,7 +3515,7 @@ cdef class RandomState:
if fleft == fright:
raise ValueError("left == right")
return cont3_array_sc(self.internal_state, rk_triangular, size, fleft,
- fmode, fright)
+ fmode, fright, self.lock)
PyErr_Clear()
oleft = <ndarray>PyArray_FROM_OTF(left, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
@@ -3402,7 +3529,7 @@ cdef class RandomState:
if np.any(np.equal(oleft, oright)):
raise ValueError("left == right")
return cont3_array(self.internal_state, rk_triangular, size, oleft,
- omode, oright)
+ omode, oright, self.lock)
# Complicated, discrete distributions:
def binomial(self, n, p, size=None):
@@ -3422,9 +3549,10 @@ cdef class RandomState:
parameter, >= 0.
p : float
parameter, >= 0 and <=1.
- size : {tuple, int}
+ 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.
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -3499,7 +3627,10 @@ cdef class RandomState:
raise ValueError("p < 0")
elif fp > 1:
raise ValueError("p > 1")
- return discnp_array_sc(self.internal_state, rk_binomial, size, ln, fp)
+ elif np.isnan(fp):
+ raise ValueError("p is nan")
+ return discnp_array_sc(self.internal_state, rk_binomial, size, ln,
+ fp, self.lock)
PyErr_Clear()
@@ -3511,7 +3642,8 @@ cdef class RandomState:
raise ValueError("p < 0")
if np.any(np.greater(p, 1)):
raise ValueError("p > 1")
- return discnp_array(self.internal_state, rk_binomial, size, on, op)
+ return discnp_array(self.internal_state, rk_binomial, size, on, op,
+ self.lock)
def negative_binomial(self, n, p, size=None):
"""
@@ -3529,9 +3661,10 @@ cdef class RandomState:
Parameter, > 0.
p : float
Parameter, >= 0 and <=1.
- size : int or tuple of ints
- Output shape. If the given shape is, e.g., ``(m, n, k)``, then
- ``m * n * k`` samples are drawn.
+ 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. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -3593,7 +3726,7 @@ cdef class RandomState:
elif fp > 1:
raise ValueError("p > 1")
return discdd_array_sc(self.internal_state, rk_negative_binomial,
- size, fn, fp)
+ size, fn, fp, self.lock)
PyErr_Clear()
@@ -3606,7 +3739,7 @@ cdef class RandomState:
if np.any(np.greater(p, 1)):
raise ValueError("p > 1")
return discdd_array(self.internal_state, rk_negative_binomial, size,
- on, op)
+ on, op, self.lock)
def poisson(self, lam=1.0, size=None):
"""
@@ -3619,11 +3752,13 @@ cdef class RandomState:
Parameters
----------
- lam : float
- Expectation of interval, should be >= 0.
+ lam : float or sequence of float
+ Expectation of interval, should be >= 0. A sequence of expectation
+ intervals must be broadcastable over the requested size.
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.
+ Output shape. If the given shape is, e.g., ``(m, n, k)``, then
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
Notes
-----
@@ -3659,6 +3794,10 @@ cdef class RandomState:
>>> count, bins, ignored = plt.hist(s, 14, normed=True)
>>> plt.show()
+ Draw each 100 values for lambda 100 and 500:
+
+ >>> s = np.random.poisson(lam=(100., 500.), size=(100, 2))
+
"""
cdef ndarray olam
cdef double flam
@@ -3668,7 +3807,8 @@ cdef class RandomState:
raise ValueError("lam < 0")
if lam > self.poisson_lam_max:
raise ValueError("lam value too large")
- return discd_array_sc(self.internal_state, rk_poisson, size, flam)
+ return discd_array_sc(self.internal_state, rk_poisson, size, flam,
+ self.lock)
PyErr_Clear()
@@ -3677,7 +3817,7 @@ cdef class RandomState:
raise ValueError("lam < 0")
if np.any(np.greater(olam, self.poisson_lam_max)):
raise ValueError("lam value too large.")
- return discd_array(self.internal_state, rk_poisson, size, olam)
+ return discd_array(self.internal_state, rk_poisson, size, olam, self.lock)
def zipf(self, a, size=None):
"""
@@ -3697,12 +3837,10 @@ cdef class RandomState:
----------
a : float > 1
Distribution parameter.
- size : int or tuple of int, optional
+ 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; a single integer is equivalent in
- its result to providing a mono-tuple, i.e., a 1-D array of length
- *size* is returned. The default is None, in which case a single
- scalar is returned.
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -3758,14 +3896,15 @@ cdef class RandomState:
if not PyErr_Occurred():
if fa <= 1.0:
raise ValueError("a <= 1.0")
- return discd_array_sc(self.internal_state, rk_zipf, size, fa)
+ return discd_array_sc(self.internal_state, rk_zipf, size, fa,
+ self.lock)
PyErr_Clear()
oa = <ndarray>PyArray_FROM_OTF(a, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
if np.any(np.less_equal(oa, 1.0)):
raise ValueError("a <= 1.0")
- return discd_array(self.internal_state, rk_zipf, size, oa)
+ return discd_array(self.internal_state, rk_zipf, size, oa, self.lock)
def geometric(self, p, size=None):
"""
@@ -3789,9 +3928,10 @@ cdef class RandomState:
----------
p : float
The probability of success of an individual trial.
- size : tuple of ints
- Number of values to draw from the distribution. The output
- is shaped according to `size`.
+ 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. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -3821,7 +3961,8 @@ cdef class RandomState:
raise ValueError("p < 0.0")
if fp > 1.0:
raise ValueError("p > 1.0")
- return discd_array_sc(self.internal_state, rk_geometric, size, fp)
+ return discd_array_sc(self.internal_state, rk_geometric, size, fp,
+ self.lock)
PyErr_Clear()
@@ -3831,7 +3972,7 @@ cdef class RandomState:
raise ValueError("p < 0.0")
if np.any(np.greater(op, 1.0)):
raise ValueError("p > 1.0")
- return discd_array(self.internal_state, rk_geometric, size, op)
+ return discd_array(self.internal_state, rk_geometric, size, op, self.lock)
def hypergeometric(self, ngood, nbad, nsample, size=None):
"""
@@ -3853,9 +3994,10 @@ cdef class RandomState:
nsample : int or array_like
Number of items sampled. Must be at least 1 and at most
``ngood + nbad``.
- size : int or tuple of int
+ 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.
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -3933,8 +4075,8 @@ cdef class RandomState:
raise ValueError("nsample < 1")
if lngood + lnbad < lnsample:
raise ValueError("ngood + nbad < nsample")
- return discnmN_array_sc(self.internal_state, rk_hypergeometric, size,
- lngood, lnbad, lnsample)
+ return discnmN_array_sc(self.internal_state, rk_hypergeometric,
+ size, lngood, lnbad, lnsample, self.lock)
PyErr_Clear()
@@ -3950,7 +4092,7 @@ cdef class RandomState:
if np.any(np.less(np.add(ongood, onbad),onsample)):
raise ValueError("ngood + nbad < nsample")
return discnmN_array(self.internal_state, rk_hypergeometric, size,
- ongood, onbad, onsample)
+ ongood, onbad, onsample, self.lock)
def logseries(self, p, size=None):
"""
@@ -3967,9 +4109,10 @@ cdef class RandomState:
scale : float > 0.
- size : {tuple, int}
+ 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.
+ ``m * n * k`` samples are drawn. Default is None, in which case a
+ single value is returned.
Returns
-------
@@ -4035,7 +4178,8 @@ cdef class RandomState:
raise ValueError("p <= 0.0")
if fp >= 1.0:
raise ValueError("p >= 1.0")
- return discd_array_sc(self.internal_state, rk_logseries, size, fp)
+ return discd_array_sc(self.internal_state, rk_logseries, size, fp,
+ self.lock)
PyErr_Clear()
@@ -4044,7 +4188,7 @@ cdef class RandomState:
raise ValueError("p <= 0.0")
if np.any(np.greater_equal(op, 1.0)):
raise ValueError("p >= 1.0")
- return discd_array(self.internal_state, rk_logseries, size, op)
+ return discd_array(self.internal_state, rk_logseries, size, op, self.lock)
# Multivariate distributions:
def multivariate_normal(self, mean, cov, size=None):
@@ -4066,7 +4210,7 @@ cdef class RandomState:
Mean of the N-dimensional distribution.
cov : 2-D array_like, of shape (N, N)
Covariance matrix of the distribution. Must be symmetric and
- positive semi-definite for "physically meaningful" results.
+ positive-semidefinite for "physically meaningful" results.
size : int or tuple of ints, optional
Given a shape of, for example, ``(m,n,k)``, ``m*n*k`` samples are
generated, and packed in an `m`-by-`n`-by-`k` arrangement. Because
@@ -4138,44 +4282,55 @@ cdef class RandomState:
[True, True]
"""
+ from numpy.dual import svd
+
# Check preconditions on arguments
mean = np.array(mean)
cov = np.array(cov)
if size is None:
shape = []
+ elif isinstance(size, (int, long, np.integer)):
+ shape = [size]
else:
shape = size
+
if len(mean.shape) != 1:
raise ValueError("mean must be 1 dimensional")
if (len(cov.shape) != 2) or (cov.shape[0] != cov.shape[1]):
raise ValueError("cov must be 2 dimensional and square")
if mean.shape[0] != cov.shape[0]:
raise ValueError("mean and cov must have same length")
- # Compute shape of output
- if isinstance(shape, (int, long, np.integer)):
- shape = [shape]
+
+ # Compute shape of output and create a matrix of independent
+ # standard normally distributed random numbers. The matrix has rows
+ # with the same length as mean and as many rows are necessary to
+ # form a matrix of shape final_shape.
final_shape = list(shape[:])
final_shape.append(mean.shape[0])
- # Create a matrix of independent standard normally distributed random
- # numbers. The matrix has rows with the same length as mean and as
- # many rows are necessary to form a matrix of shape final_shape.
- x = self.standard_normal(np.multiply.reduce(final_shape))
- x.shape = (np.multiply.reduce(final_shape[0:len(final_shape)-1]),
- mean.shape[0])
+ x = self.standard_normal(final_shape).reshape(-1, mean.shape[0])
+
# Transform matrix of standard normals into matrix where each row
# contains multivariate normals with the desired covariance.
# Compute A such that dot(transpose(A),A) == cov.
# Then the matrix products of the rows of x and A has the desired
# covariance. Note that sqrt(s)*v where (u,s,v) is the singular value
# decomposition of cov is such an A.
-
- from numpy.dual import svd
- # XXX: we really should be doing this by Cholesky decomposition
- (u,s,v) = svd(cov)
- x = np.dot(x*np.sqrt(s),v)
- # The rows of x now have the correct covariance but mean 0. Add
- # mean to each row. Then each row will have mean mean.
- np.add(mean,x,x)
+ #
+ # Also check that cov is positive-semidefinite. If so, the u.T and v
+ # matrices should be equal up to roundoff error if cov is
+ # symmetrical and the singular value of the corresponding row is
+ # not zero. We continue to use the SVD rather than Cholesky in
+ # order to preserve current outputs. Note that symmetry has not
+ # been checked.
+ (u, s, v) = svd(cov)
+ neg = (np.sum(u.T * v, axis=1) < 0) & (s > 0)
+ if np.any(neg):
+ s[neg] = 0.
+ warnings.warn("covariance is not positive-semidefinite.",
+ RuntimeWarning)
+
+ x = np.dot(x, np.sqrt(s)[:, None] * v)
+ x += mean
x.shape = tuple(final_shape)
return x
@@ -4235,7 +4390,7 @@ cdef class RandomState:
cdef ndarray parr "arrayObject_parr", mnarr "arrayObject_mnarr"
cdef double *pix
cdef long *mnix
- cdef npy_intp i, j, dn
+ cdef npy_intp i, j, dn, sz
cdef double Sum
d = len(pvals)
@@ -4245,30 +4400,27 @@ cdef class RandomState:
if kahan_sum(pix, d-1) > (1.0 + 1e-12):
raise ValueError("sum(pvals[:-1]) > 1.0")
- if size is None:
- shape = (d,)
- elif type(size) is int:
- shape = (size, d)
- else:
- shape = size + (d,)
+ shape = _shape_from_size(size, d)
multin = np.zeros(shape, int)
mnarr = <ndarray>multin
mnix = <long*>PyArray_DATA(mnarr)
- i = 0
- while i < PyArray_SIZE(mnarr):
- Sum = 1.0
- dn = n
- for j from 0 <= j < d-1:
- mnix[i+j] = rk_binomial(self.internal_state, dn, pix[j]/Sum)
- dn = dn - mnix[i+j]
- if dn <= 0:
- break
- Sum = Sum - pix[j]
- if dn > 0:
- mnix[i+d-1] = dn
-
- i = i + d
+ sz = PyArray_SIZE(mnarr)
+ with self.lock, nogil:
+ i = 0
+ while i < sz:
+ Sum = 1.0
+ dn = n
+ for j from 0 <= j < d-1:
+ mnix[i+j] = rk_binomial(self.internal_state, dn, pix[j]/Sum)
+ dn = dn - mnix[i+j]
+ if dn <= 0:
+ break
+ Sum = Sum - pix[j]
+ if dn > 0:
+ mnix[i+d-1] = dn
+
+ i = i + d
return multin
@@ -4354,7 +4506,8 @@ cdef class RandomState:
cdef npy_intp k
cdef npy_intp totsize
cdef ndarray alpha_arr, val_arr
- cdef double *alpha_data, *val_data
+ cdef double *alpha_data
+ cdef double *val_data
cdef npy_intp i, j
cdef double acc, invacc
@@ -4362,12 +4515,7 @@ cdef class RandomState:
alpha_arr = <ndarray>PyArray_ContiguousFromObject(alpha, NPY_DOUBLE, 1, 1)
alpha_data = <double*>PyArray_DATA(alpha_arr)
- if size is None:
- shape = (k,)
- elif type(size) is int:
- shape = (size, k)
- else:
- shape = size + (k,)
+ shape = _shape_from_size(size, k)
diric = np.zeros(shape, np.float64)
val_arr = <ndarray>diric
@@ -4375,15 +4523,17 @@ cdef class RandomState:
i = 0
totsize = PyArray_SIZE(val_arr)
- while i < totsize:
- acc = 0.0
- for j from 0 <= j < k:
- val_data[i+j] = rk_standard_gamma(self.internal_state, alpha_data[j])
- acc = acc + val_data[i+j]
- invacc = 1/acc
- for j from 0 <= j < k:
- val_data[i+j] = val_data[i+j] * invacc
- i = i + k
+ with self.lock, nogil:
+ while i < totsize:
+ acc = 0.0
+ for j from 0 <= j < k:
+ val_data[i+j] = rk_standard_gamma(self.internal_state,
+ alpha_data[j])
+ acc = acc + val_data[i+j]
+ invacc = 1/acc
+ for j from 0 <= j < k:
+ val_data[i+j] = val_data[i+j] * invacc
+ i = i + k
return diric
@@ -4426,11 +4576,12 @@ cdef class RandomState:
i = len(x) - 1
# Logic adapted from random.shuffle()
- if isinstance(x, np.ndarray) and x.ndim > 1:
+ if isinstance(x, np.ndarray) and \
+ (x.ndim > 1 or x.dtype.fields is not None):
# For a multi-dimensional ndarray, indexing returns a view onto
# each row. So we can't just use ordinary assignment to swap the
# rows; we need a bounce buffer.
- buf = np.empty(x.shape[1:], dtype=x.dtype)
+ buf = np.empty_like(x[0])
while i > 0:
j = rk_interval(i, self.internal_state)
buf[...] = x[j]