From 16e80594888a00137d50621892a268540edabb4b Mon Sep 17 00:00:00 2001 From: mattip Date: Fri, 29 Nov 2019 11:11:06 +0200 Subject: DOC: improve the C-API/Cython documentation for random --- doc/source/reference/random/c-api.rst | 147 ++++++++++++++++++++---------- doc/source/reference/random/extending.rst | 2 + 2 files changed, 99 insertions(+), 50 deletions(-) diff --git a/doc/source/reference/random/c-api.rst b/doc/source/reference/random/c-api.rst index 3c901f3b4..1ec2207a2 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 -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: + 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. + +The functions are named with the following cconventions: - "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,42 @@ 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. +- ``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:: double random_standard_uniform(bitgen_t *bitgen_state) -.. c:function:: void random_standard_uniform_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(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_exponential_fill(bitgen_t *bitgen_state, npy_intp cnt, double *out) .. c:function:: double random_standard_exponential_zig(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_zig_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_fill_f(bitgen_t *bitgen_state, 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_zig_fill_f(bitgen_t *bitgen_state, npy_intp cnt, float *out) .. c:function:: float random_standard_normal_f(bitgen_t* bitgen_state) @@ -121,57 +143,82 @@ It provides low-level functions for various distributions. All the functions req .. c:function:: double random_triangular(bitgen_t *bitgen_state, double left, double mode, double right) -.. c:function:: int64_t random_poisson(bitgen_t *bitgen_state, double lam) +.. 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 + + .. 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) + 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) + 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 -- cgit v1.2.1 From bcd950f0a4b6617bc3111a0ffd8102475ad1c3be Mon Sep 17 00:00:00 2001 From: mattip Date: Fri, 29 Nov 2019 14:12:19 +0200 Subject: DOC, TST: refactor CFFI test, add file names to documentation --- doc/source/reference/random/examples/cffi.rst | 2 + doc/source/reference/random/examples/numba.rst | 2 + .../reference/random/examples/numba_cffi.rst | 2 + numpy/random/_examples/cffi/extending.py | 38 ++---------------- numpy/random/_examples/cffi/parse.py | 46 ++++++++++++++++++++++ 5 files changed, 55 insertions(+), 35 deletions(-) create mode 100644 numpy/random/_examples/cffi/parse.py diff --git a/doc/source/reference/random/examples/cffi.rst b/doc/source/reference/random/examples/cffi.rst index 04d52203b..79cdf6a8f 100644 --- a/doc/source/reference/random/examples/cffi.rst +++ b/doc/source/reference/random/examples/cffi.rst @@ -1,5 +1,7 @@ Extending via CFFI ------------------ +The source of ``numpy/random/_examples/cffi/extending.py`` + .. literalinclude:: ../../../../../numpy/random/_examples/cffi/extending.py :language: python diff --git a/doc/source/reference/random/examples/numba.rst b/doc/source/reference/random/examples/numba.rst index b41a02568..1a6dd6e85 100644 --- a/doc/source/reference/random/examples/numba.rst +++ b/doc/source/reference/random/examples/numba.rst @@ -1,5 +1,7 @@ Extending via Numba ------------------- +The source of ``numpy/random/_examples/numba/extending.py`` + .. literalinclude:: ../../../../../numpy/random/_examples/numba/extending.py :language: python diff --git a/doc/source/reference/random/examples/numba_cffi.rst b/doc/source/reference/random/examples/numba_cffi.rst index fb2f85cce..c3e38537f 100644 --- a/doc/source/reference/random/examples/numba_cffi.rst +++ b/doc/source/reference/random/examples/numba_cffi.rst @@ -1,5 +1,7 @@ Extending via Numba and CFFI ---------------------------- +The source of ``numpy/random/_examples/numba/extending_distributions.py`` + .. literalinclude:: ../../../../../numpy/random/_examples/numba/extending_distributions.py :language: python 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)) + -- cgit v1.2.1 From a2acfa6f2f99207fff87f19170cb4260b775d086 Mon Sep 17 00:00:00 2001 From: mattip Date: Fri, 29 Nov 2019 15:01:28 +0200 Subject: API: rename functions in distributions.c,h --- doc/source/reference/random/c-api.rst | 12 +--- numpy/core/include/numpy/random/distributions.h | 10 ++- numpy/random/_generator.pyx | 26 ++++---- numpy/random/src/distributions/distributions.c | 85 ++++++++++++------------- 4 files changed, 57 insertions(+), 76 deletions(-) diff --git a/doc/source/reference/random/c-api.rst b/doc/source/reference/random/c-api.rst index 1ec2207a2..6087dd117 100644 --- a/doc/source/reference/random/c-api.rst +++ b/doc/source/reference/random/c-api.rst @@ -69,10 +69,6 @@ The functions are named with the following cconventions: .. c:function:: void random_standard_exponential_fill(bitgen_t *bitgen_state, npy_intp cnt, double *out) -.. c:function:: double random_standard_exponential_zig(bitgen_t *bitgen_state) - -.. c:function:: void random_standard_exponential_zig_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, npy_intp count, double *out) @@ -87,12 +83,8 @@ The functions are named with the following cconventions: .. 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, npy_intp cnt, float *out) -.. c:function:: void random_standard_exponential_zig_fill_f(bitgen_t *bitgen_state, npy_intp cnt, float *out) - .. c:function:: float random_standard_normal_f(bitgen_t* bitgen_state) .. c:function:: float random_standard_gamma_f(bitgen_t *bitgen_state, float shape) @@ -112,7 +104,7 @@ The functions are named with the following cconventions: .. c:function:: double random_f(bitgen_t *bitgen_state, double dfnum, double dfden) -.. c:function:: double random_standard_cauchy(bitgen_t *bitgen_state) +.. c:function:: double random_cauchy(bitgen_t *bitgen_state) .. c:function:: double random_pareto(bitgen_t *bitgen_state, double a) @@ -130,7 +122,7 @@ The functions are named with the following cconventions: .. c:function:: double random_rayleigh(bitgen_t *bitgen_state, double mode) -.. c:function:: double random_standard_t(bitgen_t *bitgen_state, double df) +.. c:function:: double random_student_t(bitgen_t *bitgen_state, double df) .. c:function:: double random_noncentral_chisquare(bitgen_t *bitgen_state, double df, double nonc) diff --git a/numpy/core/include/numpy/random/distributions.h b/numpy/core/include/numpy/random/distributions.h index 1a8e44e40..94451ebe7 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); @@ -95,7 +93,7 @@ DECLDIR double random_uniform(bitgen_t *bitgen_state, double lower, double range DECLDIR double random_beta(bitgen_t *bitgen_state, double a, double b); DECLDIR double random_chisquare(bitgen_t *bitgen_state, double df); DECLDIR double random_f(bitgen_t *bitgen_state, double dfnum, double dfden); -DECLDIR double random_standard_cauchy(bitgen_t *bitgen_state); +DECLDIR double random_cauchy(bitgen_t *bitgen_state); DECLDIR double random_pareto(bitgen_t *bitgen_state, double a); DECLDIR double random_weibull(bitgen_t *bitgen_state, double a); DECLDIR double random_power(bitgen_t *bitgen_state, double a); @@ -104,7 +102,7 @@ DECLDIR double random_gumbel(bitgen_t *bitgen_state, double loc, double scale); DECLDIR double random_logistic(bitgen_t *bitgen_state, double loc, double scale); DECLDIR double random_lognormal(bitgen_t *bitgen_state, double mean, double sigma); DECLDIR double random_rayleigh(bitgen_t *bitgen_state, double mode); -DECLDIR double random_standard_t(bitgen_t *bitgen_state, double df); +DECLDIR double random_student_t(bitgen_t *bitgen_state, double df); DECLDIR double random_noncentral_chisquare(bitgen_t *bitgen_state, double df, double nonc); DECLDIR double random_noncentral_f(bitgen_t *bitgen_state, double dfnum, diff --git a/numpy/random/_generator.pyx b/numpy/random/_generator.pyx index 64ec73986..6acbb8ac3 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 @@ -86,7 +84,7 @@ cdef extern from "numpy/random/distributions.h": double random_beta(bitgen_t *bitgen_state, double a, double b) nogil double random_chisquare(bitgen_t *bitgen_state, double df) nogil double random_f(bitgen_t *bitgen_state, double dfnum, double dfden) nogil - double random_standard_cauchy(bitgen_t *bitgen_state) nogil + double random_cauchy(bitgen_t *bitgen_state) nogil double random_pareto(bitgen_t *bitgen_state, double a) nogil double random_weibull(bitgen_t *bitgen_state, double a) nogil double random_power(bitgen_t *bitgen_state, double a) nogil @@ -95,7 +93,7 @@ cdef extern from "numpy/random/distributions.h": double random_logistic(bitgen_t *bitgen_state, double loc, double scale) nogil double random_lognormal(bitgen_t *bitgen_state, double mean, double sigma) nogil double random_rayleigh(bitgen_t *bitgen_state, double mode) nogil - double random_standard_t(bitgen_t *bitgen_state, double df) nogil + double random_student_t(bitgen_t *bitgen_state, double df) nogil double random_noncentral_chisquare(bitgen_t *bitgen_state, double df, double nonc) nogil double random_noncentral_f(bitgen_t *bitgen_state, double dfnum, @@ -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) @@ -1697,7 +1695,7 @@ cdef class Generator: >>> plt.show() """ - return cont(&random_standard_cauchy, &self._bitgen, size, self.lock, 0, + return cont(&random_cauchy, &self._bitgen, size, self.lock, 0, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, None) def standard_t(self, df, size=None): @@ -1788,7 +1786,7 @@ cdef class Generator: probability of about 99% of being true. """ - return cont(&random_standard_t, &self._bitgen, size, self.lock, 1, + return cont(&random_student_t, &self._bitgen, size, self.lock, 1, df, 'df', CONS_POSITIVE, 0, '', CONS_NONE, 0, '', CONS_NONE, diff --git a/numpy/random/src/distributions/distributions.c b/numpy/random/src/distributions/distributions.c index df3323408..1b886aeab 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) { @@ -450,23 +443,23 @@ double random_f(bitgen_t *bitgen_state, double dfnum, double dfden) { (random_chisquare(bitgen_state, dfden) * dfnum)); } -double random_standard_cauchy(bitgen_t *bitgen_state) { +double random_cauchy(bitgen_t *bitgen_state) { return random_standard_normal(bitgen_state) / random_standard_normal(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) { @@ -514,7 +507,7 @@ double random_rayleigh(bitgen_t *bitgen_state, double mode) { return mode * sqrt(-2.0 * log(1.0 - next_double(bitgen_state))); } -double random_standard_t(bitgen_t *bitgen_state, double df) { +double random_student_t(bitgen_t *bitgen_state, double df) { double num, denom; num = random_standard_normal(bitgen_state); -- cgit v1.2.1 From aeaee5e0ab11abc9221e8ba938a3ff010b87fe36 Mon Sep 17 00:00:00 2001 From: mattip Date: Fri, 29 Nov 2019 15:56:14 +0200 Subject: DOC: sphinx does not like breaking function declarations over lines --- doc/source/reference/random/c-api.rst | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/doc/source/reference/random/c-api.rst b/doc/source/reference/random/c-api.rst index 6087dd117..bdb6ead04 100644 --- a/doc/source/reference/random/c-api.rst +++ b/doc/source/reference/random/c-api.rst @@ -176,25 +176,15 @@ The functions are named with the following cconventions: .. c:function:: npy_int64 random_zipf(bitgen_t *bitgen_state, double a) -.. c:function:: npy_int64 random_hypergeometric(bitgen_t *bitgen_state, npy_int64 good, npy_int64 bad, - npy_int64 sample) +.. c:function:: npy_int64 random_hypergeometric(bitgen_t *bitgen_state, npy_int64 good, npy_int64 bad, npy_int64 sample) .. c:function:: npy_uint64 random_interval(bitgen_t *bitgen_state, npy_uint64 max) -.. 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:: 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, - npy_int64 total, - size_t num_colors, npy_int64 *colors, - npy_int64 nsample, - size_t num_variates, npy_int64 *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, - 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, npy_int64 total, size_t num_colors, npy_int64 *colors, npy_int64 nsample, size_t num_variates, npy_int64 *variates) Generate a single integer @@ -209,8 +199,6 @@ Generate a single integer Generate random uint64 numbers in closed interval [off, off + rng]. -.. c:function:: npy_uint64 random_bounded_uint64(bitgen_t *bitgen_state, - npy_uint64 off, npy_uint64 rng, - npy_uint64 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) -- cgit v1.2.1 From 2b791a5906a2243b4e0a3318bd460b2062416fb9 Mon Sep 17 00:00:00 2001 From: mattip Date: Sat, 30 Nov 2019 09:01:59 +0200 Subject: API: revert changes to standard_t, cauchy --- numpy/core/include/numpy/random/distributions.h | 4 ++-- numpy/random/_generator.pyx | 8 ++++---- numpy/random/src/distributions/distributions.c | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/numpy/core/include/numpy/random/distributions.h b/numpy/core/include/numpy/random/distributions.h index 94451ebe7..0e69fc508 100644 --- a/numpy/core/include/numpy/random/distributions.h +++ b/numpy/core/include/numpy/random/distributions.h @@ -93,7 +93,7 @@ DECLDIR double random_uniform(bitgen_t *bitgen_state, double lower, double range DECLDIR double random_beta(bitgen_t *bitgen_state, double a, double b); DECLDIR double random_chisquare(bitgen_t *bitgen_state, double df); DECLDIR double random_f(bitgen_t *bitgen_state, double dfnum, double dfden); -DECLDIR double random_cauchy(bitgen_t *bitgen_state); +DECLDIR double random_standard_cauchy(bitgen_t *bitgen_state); DECLDIR double random_pareto(bitgen_t *bitgen_state, double a); DECLDIR double random_weibull(bitgen_t *bitgen_state, double a); DECLDIR double random_power(bitgen_t *bitgen_state, double a); @@ -102,7 +102,7 @@ DECLDIR double random_gumbel(bitgen_t *bitgen_state, double loc, double scale); DECLDIR double random_logistic(bitgen_t *bitgen_state, double loc, double scale); DECLDIR double random_lognormal(bitgen_t *bitgen_state, double mean, double sigma); DECLDIR double random_rayleigh(bitgen_t *bitgen_state, double mode); -DECLDIR double random_student_t(bitgen_t *bitgen_state, double df); +DECLDIR double random_standard_t(bitgen_t *bitgen_state, double df); DECLDIR double random_noncentral_chisquare(bitgen_t *bitgen_state, double df, double nonc); DECLDIR double random_noncentral_f(bitgen_t *bitgen_state, double dfnum, diff --git a/numpy/random/_generator.pyx b/numpy/random/_generator.pyx index 6acbb8ac3..74b379da8 100644 --- a/numpy/random/_generator.pyx +++ b/numpy/random/_generator.pyx @@ -84,7 +84,7 @@ cdef extern from "numpy/random/distributions.h": double random_beta(bitgen_t *bitgen_state, double a, double b) nogil double random_chisquare(bitgen_t *bitgen_state, double df) nogil double random_f(bitgen_t *bitgen_state, double dfnum, double dfden) nogil - double random_cauchy(bitgen_t *bitgen_state) nogil + double random_standard_cauchy(bitgen_t *bitgen_state) nogil double random_pareto(bitgen_t *bitgen_state, double a) nogil double random_weibull(bitgen_t *bitgen_state, double a) nogil double random_power(bitgen_t *bitgen_state, double a) nogil @@ -93,7 +93,7 @@ cdef extern from "numpy/random/distributions.h": double random_logistic(bitgen_t *bitgen_state, double loc, double scale) nogil double random_lognormal(bitgen_t *bitgen_state, double mean, double sigma) nogil double random_rayleigh(bitgen_t *bitgen_state, double mode) nogil - double random_student_t(bitgen_t *bitgen_state, double df) nogil + double random_standard_t(bitgen_t *bitgen_state, double df) nogil double random_noncentral_chisquare(bitgen_t *bitgen_state, double df, double nonc) nogil double random_noncentral_f(bitgen_t *bitgen_state, double dfnum, @@ -1695,7 +1695,7 @@ cdef class Generator: >>> plt.show() """ - return cont(&random_cauchy, &self._bitgen, size, self.lock, 0, + return cont(&random_standard_cauchy, &self._bitgen, size, self.lock, 0, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, 0.0, '', CONS_NONE, None) def standard_t(self, df, size=None): @@ -1786,7 +1786,7 @@ cdef class Generator: probability of about 99% of being true. """ - return cont(&random_student_t, &self._bitgen, size, self.lock, 1, + return cont(&random_standard_t, &self._bitgen, size, self.lock, 1, df, 'df', CONS_POSITIVE, 0, '', CONS_NONE, 0, '', CONS_NONE, diff --git a/numpy/random/src/distributions/distributions.c b/numpy/random/src/distributions/distributions.c index 1b886aeab..0b46dc6d8 100644 --- a/numpy/random/src/distributions/distributions.c +++ b/numpy/random/src/distributions/distributions.c @@ -443,7 +443,7 @@ double random_f(bitgen_t *bitgen_state, double dfnum, double dfden) { (random_chisquare(bitgen_state, dfden) * dfnum)); } -double random_cauchy(bitgen_t *bitgen_state) { +double random_standard_cauchy(bitgen_t *bitgen_state) { return random_standard_normal(bitgen_state) / random_standard_normal(bitgen_state); } @@ -507,7 +507,7 @@ double random_rayleigh(bitgen_t *bitgen_state, double mode) { return mode * sqrt(-2.0 * log(1.0 - next_double(bitgen_state))); } -double random_student_t(bitgen_t *bitgen_state, double df) { +double random_standard_t(bitgen_t *bitgen_state, double df) { double num, denom; num = random_standard_normal(bitgen_state); -- cgit v1.2.1 From b2f2700469dbda3c791fb6a3a1dad1f95c4f7a8a Mon Sep 17 00:00:00 2001 From: mattip Date: Tue, 3 Dec 2019 07:43:16 +0200 Subject: DOC: fixes from review --- doc/source/reference/random/c-api.rst | 16 +++++++--------- doc/source/reference/random/examples/cffi.rst | 2 -- doc/source/reference/random/examples/numba.rst | 2 -- doc/source/reference/random/examples/numba_cffi.rst | 2 -- 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/doc/source/reference/random/c-api.rst b/doc/source/reference/random/c-api.rst index bdb6ead04..2a9de04dc 100644 --- a/doc/source/reference/random/c-api.rst +++ b/doc/source/reference/random/c-api.rst @@ -45,7 +45,7 @@ like CFFI. All the functions accept a :c:type:`bitgen_t` as their first argument See :doc:`extending` for examples of using these functions. -The functions are named with the following 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 @@ -98,13 +98,14 @@ The functions are named with the following cconventions: .. 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) .. c:function:: double random_f(bitgen_t *bitgen_state, double dfnum, double dfden) -.. c:function:: double random_cauchy(bitgen_t *bitgen_state) +.. c:function:: double random_standard_cauchy(bitgen_t *bitgen_state) .. c:function:: double random_pareto(bitgen_t *bitgen_state, double a) @@ -122,18 +123,15 @@ The functions are named with the following cconventions: .. c:function:: double random_rayleigh(bitgen_t *bitgen_state, double mode) -.. c:function:: double random_student_t(bitgen_t *bitgen_state, double df) +.. 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) diff --git a/doc/source/reference/random/examples/cffi.rst b/doc/source/reference/random/examples/cffi.rst index 79cdf6a8f..04d52203b 100644 --- a/doc/source/reference/random/examples/cffi.rst +++ b/doc/source/reference/random/examples/cffi.rst @@ -1,7 +1,5 @@ Extending via CFFI ------------------ -The source of ``numpy/random/_examples/cffi/extending.py`` - .. literalinclude:: ../../../../../numpy/random/_examples/cffi/extending.py :language: python diff --git a/doc/source/reference/random/examples/numba.rst b/doc/source/reference/random/examples/numba.rst index 1a6dd6e85..b41a02568 100644 --- a/doc/source/reference/random/examples/numba.rst +++ b/doc/source/reference/random/examples/numba.rst @@ -1,7 +1,5 @@ Extending via Numba ------------------- -The source of ``numpy/random/_examples/numba/extending.py`` - .. literalinclude:: ../../../../../numpy/random/_examples/numba/extending.py :language: python diff --git a/doc/source/reference/random/examples/numba_cffi.rst b/doc/source/reference/random/examples/numba_cffi.rst index c3e38537f..fb2f85cce 100644 --- a/doc/source/reference/random/examples/numba_cffi.rst +++ b/doc/source/reference/random/examples/numba_cffi.rst @@ -1,7 +1,5 @@ Extending via Numba and CFFI ---------------------------- -The source of ``numpy/random/_examples/numba/extending_distributions.py`` - .. literalinclude:: ../../../../../numpy/random/_examples/numba/extending_distributions.py :language: python -- cgit v1.2.1