summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRalf Gommers <ralf.gommers@gmail.com>2019-12-03 14:19:36 -0800
committerGitHub <noreply@github.com>2019-12-03 14:19:36 -0800
commitfdd8395f21a252373ff17fd43185c42e040c1b64 (patch)
tree710f8da5f935da8212730c51b84467b442204f87
parentbe773d49d49f39c4b384792fbd540bc78b53f497 (diff)
parentb2f2700469dbda3c791fb6a3a1dad1f95c4f7a8a (diff)
downloadnumpy-fdd8395f21a252373ff17fd43185c42e040c1b64.tar.gz
Merge pull request #15007 from mattip/random-c-api2
DOC, API: improve the C-API/Cython documentation and interfaces for random
-rw-r--r--doc/source/reference/random/c-api.rst153
-rw-r--r--doc/source/reference/random/extending.rst2
-rw-r--r--numpy/core/include/numpy/random/distributions.h6
-rw-r--r--numpy/random/_examples/cffi/extending.py38
-rw-r--r--numpy/random/_examples/cffi/parse.py46
-rw-r--r--numpy/random/_generator.pyx18
-rw-r--r--numpy/random/src/distributions/distributions.c81
7 files changed, 187 insertions, 157 deletions
diff --git a/doc/source/reference/random/c-api.rst b/doc/source/reference/random/c-api.rst
index 3c901f3b4..2a9de04dc 100644
--- a/doc/source/reference/random/c-api.rst
+++ b/doc/source/reference/random/c-api.rst
@@ -3,32 +3,49 @@ Cython API for random
.. currentmodule:: numpy.random
-Typed versions of many of the `Generator` and `BitGenerator` can be accessed
-directly from Cython: the complete list is given below.
+Typed versions of many of the `Generator` and `BitGenerator` methods can be
+accessed directly from Cython: the complete list is given below.
The ``_bit_generator`` module is usable via::
cimport numpy.random._bit_generator
It provides function pointers for quickly accessing the next bytes in the
-`BitGenerator`::
+`BitGenerator` via a :c:type:`bitgen_t` struct.
- struct bitgen:
- void *state
- uint64_t (*next_uint64)(void *st) nogil
- uint32_t (*next_uint32)(void *st) nogil
- double (*next_double)(void *st) nogil
- uint64_t (*next_raw)(void *st) nogil
+The ``_generator`` module is usable via::
- ctypedef bitgen bitgen_t
+ cimport numpy.random._generator
-See `extending` for examples of using these functions.
+It provides low-level functions for various distributions. All the functions
+require a ``bitgen_t`` BitGenerator structure.
-The ``_generator`` module is usable via::
+C API for random
+---------------------
- cimport numpy.random._generator
+Access to various distributions is available via Cython or C-wrapper libraries
+like CFFI. All the functions accept a :c:type:`bitgen_t` as their first argument.
+
+.. c:type:: bitgen_t
+
+ The :c:type:`bitgen_t` holds the current state of the BitGenerator and
+ pointers to functions that return standard C types while advancing the
+ state.
+
+ .. code-block:: c
+
+ struct bitgen:
+ void *state
+ npy_uint64 (*next_uint64)(void *st) nogil
+ uint32_t (*next_uint32)(void *st) nogil
+ double (*next_double)(void *st) nogil
+ npy_uint64 (*next_raw)(void *st) nogil
+
+ ctypedef bitgen bitgen_t
+
+See :doc:`extending` for examples of using these functions.
-It provides low-level functions for various distributions. All the functions require a ``bitgen_t`` BitGenerator structure. The functions are named with the followig cconventions:
+The functions are named with the following conventions:
- "standard" refers to the reference values for any parameters. For instance
"standard_uniform" means a uniform distribution on the interval ``0.0`` to
@@ -39,37 +56,34 @@ It provides low-level functions for various distributions. All the functions req
- The functions without "standard" in their name require additional parameters
to describe the distributions.
-.. c:function:: double random_standard_uniform(bitgen_t *bitgen_state)
+- ``zig`` in the name are based on a ziggurat lookup algorithm is used instead
+ of calculating the ``log``, which is significantly faster. The non-ziggurat
+ variants are used in corner cases and for legacy compatibility.
-.. c:function:: void random_standard_uniform_fill(bitgen_t* bitgen_state, np.npy_intp cnt, double *out)
-.. c:function:: double random_standard_exponential(bitgen_t *bitgen_state)
+.. c:function:: double random_standard_uniform(bitgen_t *bitgen_state)
-.. c:function:: void random_standard_exponential_fill(bitgen_t *bitgen_state, np.npy_intp cnt, double *out)
+.. c:function:: void random_standard_uniform_fill(bitgen_t* bitgen_state, npy_intp cnt, double *out)
-.. c:function:: double random_standard_exponential_zig(bitgen_t *bitgen_state)
+.. c:function:: double random_standard_exponential(bitgen_t *bitgen_state)
-.. c:function:: void random_standard_exponential_zig_fill(bitgen_t *bitgen_state, np.npy_intp cnt, double *out)
+.. c:function:: void random_standard_exponential_fill(bitgen_t *bitgen_state, npy_intp cnt, double *out)
.. c:function:: double random_standard_normal(bitgen_t* bitgen_state)
-.. c:function:: void random_standard_normal_fill(bitgen_t *bitgen_state, np.npy_intp count, double *out)
+.. c:function:: void random_standard_normal_fill(bitgen_t *bitgen_state, npy_intp count, double *out)
-.. c:function:: void random_standard_normal_fill_f(bitgen_t *bitgen_state, np.npy_intp count, float *out)
+.. c:function:: void random_standard_normal_fill_f(bitgen_t *bitgen_state, npy_intp count, float *out)
.. c:function:: double random_standard_gamma(bitgen_t *bitgen_state, double shape)
.. c:function:: float random_standard_uniform_f(bitgen_t *bitgen_state)
-.. c:function:: void random_standard_uniform_fill_f(bitgen_t* bitgen_state, np.npy_intp cnt, float *out)
+.. c:function:: void random_standard_uniform_fill_f(bitgen_t* bitgen_state, npy_intp cnt, float *out)
.. c:function:: float random_standard_exponential_f(bitgen_t *bitgen_state)
-.. c:function:: float random_standard_exponential_zig_f(bitgen_t *bitgen_state)
-
-.. c:function:: void random_standard_exponential_fill_f(bitgen_t *bitgen_state, np.npy_intp cnt, float *out)
-
-.. c:function:: void random_standard_exponential_zig_fill_f(bitgen_t *bitgen_state, np.npy_intp cnt, float *out)
+.. c:function:: void random_standard_exponential_fill_f(bitgen_t *bitgen_state, npy_intp cnt, float *out)
.. c:function:: float random_standard_normal_f(bitgen_t* bitgen_state)
@@ -84,6 +98,7 @@ It provides low-level functions for various distributions. All the functions req
.. c:function:: double random_exponential(bitgen_t *bitgen_state, double scale)
.. c:function:: double random_uniform(bitgen_t *bitgen_state, double lower, double range)
+
.. c:function:: double random_beta(bitgen_t *bitgen_state, double a, double b)
.. c:function:: double random_chisquare(bitgen_t *bitgen_state, double df)
@@ -110,68 +125,78 @@ It provides low-level functions for various distributions. All the functions req
.. c:function:: double random_standard_t(bitgen_t *bitgen_state, double df)
-.. c:function:: double random_noncentral_chisquare(bitgen_t *bitgen_state, double df,
- double nonc)
-.. c:function:: double random_noncentral_f(bitgen_t *bitgen_state, double dfnum,
- double dfden, double nonc)
+.. c:function:: double random_noncentral_chisquare(bitgen_t *bitgen_state, double df, double nonc)
+.. c:function:: double random_noncentral_f(bitgen_t *bitgen_state, double dfnum, double dfden, double nonc)
.. c:function:: double random_wald(bitgen_t *bitgen_state, double mean, double scale)
.. c:function:: double random_vonmises(bitgen_t *bitgen_state, double mu, double kappa)
-.. c:function:: double random_triangular(bitgen_t *bitgen_state, double left, double mode,
- double right)
+.. c:function:: double random_triangular(bitgen_t *bitgen_state, double left, double mode, double right)
+
+.. c:function:: npy_int64 random_poisson(bitgen_t *bitgen_state, double lam)
+
+.. c:function:: npy_int64 random_negative_binomial(bitgen_t *bitgen_state, double n, double p)
+
+.. c:type:: binomial_t
-.. c:function:: int64_t random_poisson(bitgen_t *bitgen_state, double lam)
+ .. code-block:: c
-.. c:function:: int64_t random_negative_binomial(bitgen_t *bitgen_state, double n, double p)
+ typedef struct s_binomial_t {
+ int has_binomial; /* !=0: following parameters initialized for binomial */
+ double psave;
+ RAND_INT_TYPE nsave;
+ double r;
+ double q;
+ double fm;
+ RAND_INT_TYPE m;
+ double p1;
+ double xm;
+ double xl;
+ double xr;
+ double c;
+ double laml;
+ double lamr;
+ double p2;
+ double p3;
+ double p4;
+ } binomial_t;
+
-.. c:function:: int64_t random_binomial(bitgen_t *bitgen_state, double p, int64_t n, binomial_t *binomial)
+.. c:function:: npy_int64 random_binomial(bitgen_t *bitgen_state, double p, npy_int64 n, binomial_t *binomial)
-.. c:function:: int64_t random_logseries(bitgen_t *bitgen_state, double p)
+.. c:function:: npy_int64 random_logseries(bitgen_t *bitgen_state, double p)
-.. c:function:: int64_t random_geometric_search(bitgen_t *bitgen_state, double p)
+.. c:function:: npy_int64 random_geometric_search(bitgen_t *bitgen_state, double p)
-.. c:function:: int64_t random_geometric_inversion(bitgen_t *bitgen_state, double p)
+.. c:function:: npy_int64 random_geometric_inversion(bitgen_t *bitgen_state, double p)
-.. c:function:: int64_t random_geometric(bitgen_t *bitgen_state, double p)
+.. c:function:: npy_int64 random_geometric(bitgen_t *bitgen_state, double p)
-.. c:function:: int64_t random_zipf(bitgen_t *bitgen_state, double a)
+.. c:function:: npy_int64 random_zipf(bitgen_t *bitgen_state, double a)
-.. c:function:: int64_t random_hypergeometric(bitgen_t *bitgen_state, int64_t good, int64_t bad,
- int64_t sample)
+.. c:function:: npy_int64 random_hypergeometric(bitgen_t *bitgen_state, npy_int64 good, npy_int64 bad, npy_int64 sample)
-.. c:function:: uint64_t random_interval(bitgen_t *bitgen_state, uint64_t max)
+.. c:function:: npy_uint64 random_interval(bitgen_t *bitgen_state, npy_uint64 max)
-.. c:function:: void random_multinomial(bitgen_t *bitgen_state, int64_t n, int64_t *mnix,
- double *pix, np.npy_intp d, binomial_t *binomial)
+.. c:function:: void random_multinomial(bitgen_t *bitgen_state, npy_int64 n, npy_int64 *mnix, double *pix, npy_intp d, binomial_t *binomial)
-.. c:function:: int random_mvhg_count(bitgen_t *bitgen_state,
- int64_t total,
- size_t num_colors, int64_t *colors,
- int64_t nsample,
- size_t num_variates, int64_t *variates)
+.. c:function:: int random_mvhg_count(bitgen_t *bitgen_state, npy_int64 total, size_t num_colors, npy_int64 *colors, npy_int64 nsample, size_t num_variates, npy_int64 *variates)
-.. c:function:: void random_mvhg_marginals(bitgen_t *bitgen_state,
- int64_t total,
- size_t num_colors, int64_t *colors,
- int64_t nsample,
- size_t num_variates, int64_t *variates)
+.. c:function:: void random_mvhg_marginals(bitgen_t *bitgen_state, npy_int64 total, size_t num_colors, npy_int64 *colors, npy_int64 nsample, size_t num_variates, npy_int64 *variates)
Generate a single integer
-.. c:function:: int64_t random_positive_int64(bitgen_t *bitgen_state)
+.. c:function:: npy_int64 random_positive_int64(bitgen_t *bitgen_state)
-.. c:function:: int32_t random_positive_int32(bitgen_t *bitgen_state)
+.. c:function:: npy_int32 random_positive_int32(bitgen_t *bitgen_state)
-.. c:function:: int64_t random_positive_int(bitgen_t *bitgen_state)
+.. c:function:: npy_int64 random_positive_int(bitgen_t *bitgen_state)
-.. c:function:: uint64_t random_uint(bitgen_t *bitgen_state)
+.. c:function:: npy_uint64 random_uint(bitgen_t *bitgen_state)
Generate random uint64 numbers in closed interval [off, off + rng].
-.. c:function:: uint64_t random_bounded_uint64(bitgen_t *bitgen_state,
- uint64_t off, uint64_t rng,
- uint64_t mask, bint use_masked)
+.. c:function:: npy_uint64 random_bounded_uint64(bitgen_t *bitgen_state, npy_uint64 off, npy_uint64 rng, npy_uint64 mask, bint use_masked)
diff --git a/doc/source/reference/random/extending.rst b/doc/source/reference/random/extending.rst
index 3c30e5623..12311379d 100644
--- a/doc/source/reference/random/extending.rst
+++ b/doc/source/reference/random/extending.rst
@@ -1,5 +1,7 @@
.. currentmodule:: numpy.random
+.. _extending:
+
Extending
---------
The BitGenerators have been designed to be extendable using standard tools for
diff --git a/numpy/core/include/numpy/random/distributions.h b/numpy/core/include/numpy/random/distributions.h
index 1a8e44e40..0e69fc508 100644
--- a/numpy/core/include/numpy/random/distributions.h
+++ b/numpy/core/include/numpy/random/distributions.h
@@ -71,12 +71,10 @@ DECLDIR uint64_t random_uint(bitgen_t *bitgen_state);
DECLDIR double random_standard_exponential(bitgen_t *bitgen_state);
DECLDIR float random_standard_exponential_f(bitgen_t *bitgen_state);
-DECLDIR double random_standard_exponential_zig(bitgen_t *bitgen_state);
-DECLDIR float random_standard_exponential_zig_f(bitgen_t *bitgen_state);
DECLDIR void random_standard_exponential_fill(bitgen_t *, npy_intp, double *);
DECLDIR void random_standard_exponential_fill_f(bitgen_t *, npy_intp, float *);
-DECLDIR void random_standard_exponential_zig_fill(bitgen_t *, npy_intp, double *);
-DECLDIR void random_standard_exponential_zig_fill_f(bitgen_t *, npy_intp, float *);
+DECLDIR void random_standard_exponential_inv_fill(bitgen_t *, npy_intp, double *);
+DECLDIR void random_standard_exponential_inv_fill_f(bitgen_t *, npy_intp, float *);
DECLDIR double random_standard_normal(bitgen_t *bitgen_state);
DECLDIR float random_standard_normal_f(bitgen_t *bitgen_state);
diff --git a/numpy/random/_examples/cffi/extending.py b/numpy/random/_examples/cffi/extending.py
index 732cbbb1d..8440d400e 100644
--- a/numpy/random/_examples/cffi/extending.py
+++ b/numpy/random/_examples/cffi/extending.py
@@ -1,9 +1,10 @@
"""
-Use cffi to access the underlying C functions from distributions.h
+Use cffi to access any of the underlying C functions from distributions.h
"""
import os
import numpy as np
import cffi
+from .parse import parse_distributions_h
ffi = cffi.FFI()
inc_dir = os.path.join(np.get_include(), 'numpy')
@@ -15,40 +16,7 @@ ffi.cdef('''
''')
-with open(os.path.join(inc_dir, 'random', 'bitgen.h')) as fid:
- s = []
- for line in fid:
- # massage the include file
- if line.strip().startswith('#'):
- continue
- s.append(line)
- ffi.cdef('\n'.join(s))
-
-with open(os.path.join(inc_dir, 'random', 'distributions.h')) as fid:
- s = []
- in_skip = 0
- for line in fid:
- # massage the include file
- if line.strip().startswith('#'):
- continue
-
- # skip any inlined function definition
- # which starts with 'static NPY_INLINE xxx(...) {'
- # and ends with a closing '}'
- if line.strip().startswith('static NPY_INLINE'):
- in_skip += line.count('{')
- continue
- elif in_skip > 0:
- in_skip += line.count('{')
- in_skip -= line.count('}')
- continue
-
- # replace defines with their value or remove them
- line = line.replace('DECLDIR', '')
- line = line.replace('NPY_INLINE', '')
- line = line.replace('RAND_INT_TYPE', 'int64_t')
- s.append(line)
- ffi.cdef('\n'.join(s))
+parse_distributions_h(ffi, inc_dir)
lib = ffi.dlopen(np.random._generator.__file__)
diff --git a/numpy/random/_examples/cffi/parse.py b/numpy/random/_examples/cffi/parse.py
new file mode 100644
index 000000000..73d8646c7
--- /dev/null
+++ b/numpy/random/_examples/cffi/parse.py
@@ -0,0 +1,46 @@
+import os
+
+
+def parse_distributions_h(ffi, inc_dir):
+ """
+ Parse distributions.h located in inc_dir for CFFI, filling in the ffi.cdef
+
+ Read the function declarations without the "#define ..." macros that will
+ be filled in when loading the library.
+ """
+
+ with open(os.path.join(inc_dir, 'random', 'bitgen.h')) as fid:
+ s = []
+ for line in fid:
+ # massage the include file
+ if line.strip().startswith('#'):
+ continue
+ s.append(line)
+ ffi.cdef('\n'.join(s))
+
+ with open(os.path.join(inc_dir, 'random', 'distributions.h')) as fid:
+ s = []
+ in_skip = 0
+ for line in fid:
+ # massage the include file
+ if line.strip().startswith('#'):
+ continue
+
+ # skip any inlined function definition
+ # which starts with 'static NPY_INLINE xxx(...) {'
+ # and ends with a closing '}'
+ if line.strip().startswith('static NPY_INLINE'):
+ in_skip += line.count('{')
+ continue
+ elif in_skip > 0:
+ in_skip += line.count('{')
+ in_skip -= line.count('}')
+ continue
+
+ # replace defines with their value or remove them
+ line = line.replace('DECLDIR', '')
+ line = line.replace('NPY_INLINE', '')
+ line = line.replace('RAND_INT_TYPE', 'int64_t')
+ s.append(line)
+ ffi.cdef('\n'.join(s))
+
diff --git a/numpy/random/_generator.pyx b/numpy/random/_generator.pyx
index 64ec73986..74b379da8 100644
--- a/numpy/random/_generator.pyx
+++ b/numpy/random/_generator.pyx
@@ -54,9 +54,11 @@ cdef extern from "numpy/random/distributions.h":
double random_standard_uniform(bitgen_t *bitgen_state) nogil
void random_standard_uniform_fill(bitgen_t* bitgen_state, np.npy_intp cnt, double *out) nogil
double random_standard_exponential(bitgen_t *bitgen_state) nogil
+ double random_standard_exponential_f(bitgen_t *bitgen_state) nogil
void random_standard_exponential_fill(bitgen_t *bitgen_state, np.npy_intp cnt, double *out) nogil
- double random_standard_exponential_zig(bitgen_t *bitgen_state) nogil
- void random_standard_exponential_zig_fill(bitgen_t *bitgen_state, np.npy_intp cnt, double *out) nogil
+ void random_standard_exponential_fill_f(bitgen_t *bitgen_state, np.npy_intp cnt, double *out) nogil
+ void random_standard_exponential_inv_fill(bitgen_t *bitgen_state, np.npy_intp cnt, double *out) nogil
+ void random_standard_exponential_inv_fill_f(bitgen_t *bitgen_state, np.npy_intp cnt, double *out) nogil
double random_standard_normal(bitgen_t* bitgen_state) nogil
void random_standard_normal_fill(bitgen_t *bitgen_state, np.npy_intp count, double *out) nogil
void random_standard_normal_fill_f(bitgen_t *bitgen_state, np.npy_intp count, float *out) nogil
@@ -64,10 +66,6 @@ cdef extern from "numpy/random/distributions.h":
float random_standard_uniform_f(bitgen_t *bitgen_state) nogil
void random_standard_uniform_fill_f(bitgen_t* bitgen_state, np.npy_intp cnt, float *out) nogil
- float random_standard_exponential_f(bitgen_t *bitgen_state) nogil
- float random_standard_exponential_zig_f(bitgen_t *bitgen_state) nogil
- void random_standard_exponential_fill_f(bitgen_t *bitgen_state, np.npy_intp cnt, float *out) nogil
- void random_standard_exponential_zig_fill_f(bitgen_t *bitgen_state, np.npy_intp cnt, float *out) nogil
float random_standard_normal_f(bitgen_t* bitgen_state) nogil
float random_standard_gamma_f(bitgen_t *bitgen_state, float shape) nogil
@@ -459,14 +457,14 @@ cdef class Generator:
key = np.dtype(dtype).name
if key == 'float64':
if method == u'zig':
- return double_fill(&random_standard_exponential_zig_fill, &self._bitgen, size, self.lock, out)
- else:
return double_fill(&random_standard_exponential_fill, &self._bitgen, size, self.lock, out)
+ else:
+ return double_fill(&random_standard_exponential_inv_fill, &self._bitgen, size, self.lock, out)
elif key == 'float32':
if method == u'zig':
- return float_fill(&random_standard_exponential_zig_fill_f, &self._bitgen, size, self.lock, out)
- else:
return float_fill(&random_standard_exponential_fill_f, &self._bitgen, size, self.lock, out)
+ else:
+ return float_fill(&random_standard_exponential_inv_fill_f, &self._bitgen, size, self.lock, out)
else:
raise TypeError('Unsupported dtype "%s" for standard_exponential'
% key)
diff --git a/numpy/random/src/distributions/distributions.c b/numpy/random/src/distributions/distributions.c
index df3323408..0b46dc6d8 100644
--- a/numpy/random/src/distributions/distributions.c
+++ b/numpy/random/src/distributions/distributions.c
@@ -41,19 +41,7 @@ void random_standard_uniform_fill_f(bitgen_t *bitgen_state, npy_intp cnt, float
}
}
-double random_standard_exponential(bitgen_t *bitgen_state) {
- return -log(1.0 - next_double(bitgen_state));
-}
-
-void random_standard_exponential_fill(bitgen_t * bitgen_state, npy_intp cnt, double * out)
-{
- npy_intp i;
- for (i = 0; i < cnt; i++) {
- out[i] = random_standard_exponential(bitgen_state);
- }
-}
-
-static double standard_exponential_zig_unlikely(bitgen_t *bitgen_state,
+static double standard_exponential_unlikely(bitgen_t *bitgen_state,
uint8_t idx, double x) {
if (idx == 0) {
/* Switch to 1.0 - U to avoid log(0.0), see GH 13361 */
@@ -63,11 +51,11 @@ static double standard_exponential_zig_unlikely(bitgen_t *bitgen_state,
exp(-x)) {
return x;
} else {
- return random_standard_exponential_zig(bitgen_state);
+ return random_standard_exponential(bitgen_state);
}
}
-double random_standard_exponential_zig(bitgen_t *bitgen_state) {
+double random_standard_exponential(bitgen_t *bitgen_state) {
uint64_t ri;
uint8_t idx;
double x;
@@ -79,30 +67,18 @@ double random_standard_exponential_zig(bitgen_t *bitgen_state) {
if (ri < ke_double[idx]) {
return x; /* 98.9% of the time we return here 1st try */
}
- return standard_exponential_zig_unlikely(bitgen_state, idx, x);
-}
-
-void random_standard_exponential_zig_fill(bitgen_t * bitgen_state, npy_intp cnt, double * out)
-{
- npy_intp i;
- for (i = 0; i < cnt; i++) {
- out[i] = random_standard_exponential_zig(bitgen_state);
- }
-}
-
-float random_standard_exponential_f(bitgen_t *bitgen_state) {
- return -logf(1.0f - next_float(bitgen_state));
+ return standard_exponential_unlikely(bitgen_state, idx, x);
}
-void random_standard_exponential_fill_f(bitgen_t * bitgen_state, npy_intp cnt, float * out)
+void random_standard_exponential_fill(bitgen_t * bitgen_state, npy_intp cnt, double * out)
{
npy_intp i;
for (i = 0; i < cnt; i++) {
- out[i] = random_standard_exponential_f(bitgen_state);
+ out[i] = random_standard_exponential(bitgen_state);
}
}
-static float standard_exponential_zig_unlikely_f(bitgen_t *bitgen_state,
+static float standard_exponential_unlikely_f(bitgen_t *bitgen_state,
uint8_t idx, float x) {
if (idx == 0) {
/* Switch to 1.0 - U to avoid log(0.0), see GH 13361 */
@@ -112,11 +88,11 @@ static float standard_exponential_zig_unlikely_f(bitgen_t *bitgen_state,
expf(-x)) {
return x;
} else {
- return random_standard_exponential_zig_f(bitgen_state);
+ return random_standard_exponential_f(bitgen_state);
}
}
-float random_standard_exponential_zig_f(bitgen_t *bitgen_state) {
+float random_standard_exponential_f(bitgen_t *bitgen_state) {
uint32_t ri;
uint8_t idx;
float x;
@@ -128,17 +104,34 @@ float random_standard_exponential_zig_f(bitgen_t *bitgen_state) {
if (ri < ke_float[idx]) {
return x; /* 98.9% of the time we return here 1st try */
}
- return standard_exponential_zig_unlikely_f(bitgen_state, idx, x);
+ return standard_exponential_unlikely_f(bitgen_state, idx, x);
+}
+
+void random_standard_exponential_fill_f(bitgen_t * bitgen_state, npy_intp cnt, float * out)
+{
+ npy_intp i;
+ for (i = 0; i < cnt; i++) {
+ out[i] = random_standard_exponential_f(bitgen_state);
+ }
+}
+
+void random_standard_exponential_inv_fill(bitgen_t * bitgen_state, npy_intp cnt, double * out)
+{
+ npy_intp i;
+ for (i = 0; i < cnt; i++) {
+ out[i] = -log(1.0 - next_double(bitgen_state));
+ }
}
-void random_standard_exponential_zig_fill_f(bitgen_t * bitgen_state, npy_intp cnt, float * out)
+void random_standard_exponential_inv_fill_f(bitgen_t * bitgen_state, npy_intp cnt, float * out)
{
npy_intp i;
for (i = 0; i < cnt; i++) {
- out[i] = random_standard_exponential_zig_f(bitgen_state);
+ out[i] = -log(1.0 - next_float(bitgen_state));
}
}
+
double random_standard_normal(bitgen_t *bitgen_state) {
uint64_t r;
int sign;
@@ -228,13 +221,13 @@ double random_standard_gamma(bitgen_t *bitgen_state,
double U, V, X, Y;
if (shape == 1.0) {
- return random_standard_exponential_zig(bitgen_state);
+ return random_standard_exponential(bitgen_state);
} else if (shape == 0.0) {
return 0.0;
} else if (shape < 1.0) {
for (;;) {
U = next_double(bitgen_state);
- V = random_standard_exponential_zig(bitgen_state);
+ V = random_standard_exponential(bitgen_state);
if (U <= 1.0 - shape) {
X = pow(U, 1. / shape);
if (X <= V) {
@@ -274,13 +267,13 @@ float random_standard_gamma_f(bitgen_t *bitgen_state,
float U, V, X, Y;
if (shape == 1.0f) {
- return random_standard_exponential_zig_f(bitgen_state);
+ return random_standard_exponential_f(bitgen_state);
} else if (shape == 0.0) {
return 0.0;
} else if (shape < 1.0f) {
for (;;) {
U = next_float(bitgen_state);
- V = random_standard_exponential_zig_f(bitgen_state);
+ V = random_standard_exponential_f(bitgen_state);
if (U <= 1.0f - shape) {
X = powf(U, 1.0f / shape);
if (X <= V) {
@@ -391,7 +384,7 @@ double random_normal(bitgen_t *bitgen_state, double loc, double scale) {
}
double random_exponential(bitgen_t *bitgen_state, double scale) {
- return scale * random_standard_exponential_zig(bitgen_state);
+ return scale * random_standard_exponential(bitgen_state);
}
double random_uniform(bitgen_t *bitgen_state, double lower, double range) {
@@ -455,18 +448,18 @@ double random_standard_cauchy(bitgen_t *bitgen_state) {
}
double random_pareto(bitgen_t *bitgen_state, double a) {
- return exp(random_standard_exponential_zig(bitgen_state) / a) - 1;
+ return exp(random_standard_exponential(bitgen_state) / a) - 1;
}
double random_weibull(bitgen_t *bitgen_state, double a) {
if (a == 0.0) {
return 0.0;
}
- return pow(random_standard_exponential_zig(bitgen_state), 1. / a);
+ return pow(random_standard_exponential(bitgen_state), 1. / a);
}
double random_power(bitgen_t *bitgen_state, double a) {
- return pow(1 - exp(-random_standard_exponential_zig(bitgen_state)), 1. / a);
+ return pow(1 - exp(-random_standard_exponential(bitgen_state)), 1. / a);
}
double random_laplace(bitgen_t *bitgen_state, double loc, double scale) {