summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
authorMatti Picus <matti.picus@gmail.com>2020-03-17 00:02:06 +0200
committerGitHub <noreply@github.com>2020-03-16 17:02:06 -0500
commit4f2b219647ae6a7928590be2b709894ae2403274 (patch)
tree5448d5f350fdcbc2546f82dfe80bd4d3e0665ada /numpy
parentf77c5e83c07985aacbddb89525785a3f66ce1b3b (diff)
downloadnumpy-4f2b219647ae6a7928590be2b709894ae2403274.tar.gz
BUG: add missing c_distributions.pxd, enables cython use of random C-API (gh-15463)
xref gh-14778 As pointed out in the comment by @jamesthomasgriffin, we did not include a pxd file to expose the distribution functions documented in the random c-api. This PR adds a c_distributions.pxd file that exposes them. Squashed commits: * BUG: add missing c_distributions.pxd to enable cython use of random C-API * ENH, TST: add npyrandom library like npymath, test cython use of it * BUG: actually prefix f-string with f * MAINT: fixes from review, add _bit_generato_bit_generator.pxd * STY: fixes from review * BLD: don't use nprandom library for mtrand legacy build * TST: WindowsPath cannot be used in subprocess's list2cmdline * MAINT, API: move _bit_generator to bit_generator * DOC: add release note about moving bit_generator * DOC, MAINT: fixes from review * MAINT: redo dtype determination from review
Diffstat (limited to 'numpy')
-rw-r--r--numpy/random/__init__.pxd2
-rw-r--r--numpy/random/__init__.py2
-rw-r--r--numpy/random/_examples/cython/extending_distributions.pyx45
-rw-r--r--numpy/random/_examples/cython/setup.py8
-rw-r--r--numpy/random/_generator.pyx110
-rw-r--r--numpy/random/bit_generator.pxd (renamed from numpy/random/_bit_generator.pxd)0
-rw-r--r--numpy/random/bit_generator.pyx (renamed from numpy/random/_bit_generator.pyx)2
-rw-r--r--numpy/random/c_distributions.pxd114
-rw-r--r--numpy/random/setup.py72
-rw-r--r--numpy/random/tests/test_direct.py2
-rw-r--r--numpy/random/tests/test_extending.py36
-rw-r--r--numpy/tests/test_public_api.py1
12 files changed, 245 insertions, 149 deletions
diff --git a/numpy/random/__init__.pxd b/numpy/random/__init__.pxd
index 05e073876..1f9057296 100644
--- a/numpy/random/__init__.pxd
+++ b/numpy/random/__init__.pxd
@@ -11,4 +11,4 @@ cdef extern from "numpy/random/bitgen.h":
ctypedef bitgen bitgen_t
-from numpy.random._bit_generator cimport BitGenerator, SeedSequence
+from numpy.random.bit_generator cimport BitGenerator, SeedSequence
diff --git a/numpy/random/__init__.py b/numpy/random/__init__.py
index 0b80999d8..7efa5c07f 100644
--- a/numpy/random/__init__.py
+++ b/numpy/random/__init__.py
@@ -181,7 +181,7 @@ from . import _common
from . import _bounded_integers
from ._generator import Generator, default_rng
-from ._bit_generator import SeedSequence, BitGenerator
+from .bit_generator import SeedSequence, BitGenerator
from ._mt19937 import MT19937
from ._pcg64 import PCG64
from ._philox import Philox
diff --git a/numpy/random/_examples/cython/extending_distributions.pyx b/numpy/random/_examples/cython/extending_distributions.pyx
index 4da6a4b3a..d908e92d0 100644
--- a/numpy/random/_examples/cython/extending_distributions.pyx
+++ b/numpy/random/_examples/cython/extending_distributions.pyx
@@ -10,6 +10,8 @@ from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer
from libc.stdint cimport uint16_t, uint64_t
from numpy.random cimport bitgen_t
from numpy.random import PCG64
+from numpy.random.c_distributions cimport (
+ random_standard_uniform_fill, random_standard_uniform_fill_f)
@cython.boundscheck(False)
@@ -40,7 +42,7 @@ def uniforms(Py_ssize_t n):
randoms = np.asarray(random_values)
return randoms
-
+
# cython example 2
@cython.boundscheck(False)
@cython.wraparound(False)
@@ -72,3 +74,44 @@ def uint10_uniforms(Py_ssize_t n):
randoms = np.asarray(random_values)
return randoms
+# cython example 3
+def uniforms_ex(bit_generator, Py_ssize_t n, dtype=np.float64):
+ """
+ Create an array of `n` uniformly distributed doubles via a "fill" function.
+
+ A 'real' distribution would want to process the values into
+ some non-uniform distribution
+
+ Parameters
+ ----------
+ bit_generator: BitGenerator instance
+ n: int
+ Output vector length
+ dtype: {str, dtype}, optional
+ Desired dtype, either 'd' (or 'float64') or 'f' (or 'float32'). The
+ default dtype value is 'd'
+ """
+ cdef Py_ssize_t i
+ cdef bitgen_t *rng
+ cdef const char *capsule_name = "BitGenerator"
+ cdef np.ndarray randoms
+
+ capsule = bit_generator.capsule
+ # Optional check that the capsule if from a BitGenerator
+ if not PyCapsule_IsValid(capsule, capsule_name):
+ raise ValueError("Invalid pointer to anon_func_state")
+ # Cast the pointer
+ rng = <bitgen_t *> PyCapsule_GetPointer(capsule, capsule_name)
+
+ _dtype = np.dtype(dtype)
+ randoms = np.empty(n, dtype=_dtype)
+ if _dtype == np.float32:
+ with bit_generator.lock:
+ random_standard_uniform_fill_f(rng, n, <float*>np.PyArray_DATA(randoms))
+ elif _dtype == np.float64:
+ with bit_generator.lock:
+ random_standard_uniform_fill(rng, n, <double*>np.PyArray_DATA(randoms))
+ else:
+ raise TypeError('Unsupported dtype %r for random' % _dtype)
+ return randoms
+
diff --git a/numpy/random/_examples/cython/setup.py b/numpy/random/_examples/cython/setup.py
index 20cedc4e3..42425c2c1 100644
--- a/numpy/random/_examples/cython/setup.py
+++ b/numpy/random/_examples/cython/setup.py
@@ -12,7 +12,11 @@ from setuptools.extension import Extension
from os.path import join, dirname
path = dirname(__file__)
+src_dir = join(dirname(path), '..', 'src')
defs = [('NPY_NO_DEPRECATED_API', 0)]
+inc_path = np.get_include()
+# not so nice. We need the random/lib library from numpy
+lib_path = join(np.get_include(), '..', '..', 'random', 'lib')
extending = Extension("extending",
sources=[join(path, 'extending.pyx')],
@@ -24,7 +28,9 @@ extending = Extension("extending",
)
distributions = Extension("extending_distributions",
sources=[join(path, 'extending_distributions.pyx')],
- include_dirs=[np.get_include()],
+ include_dirs=[inc_path],
+ library_dirs=[lib_path],
+ libraries=['npyrandom'],
define_macros=defs,
)
diff --git a/numpy/random/_generator.pyx b/numpy/random/_generator.pyx
index a3c2e0976..7766f8b8c 100644
--- a/numpy/random/_generator.pyx
+++ b/numpy/random/_generator.pyx
@@ -11,6 +11,7 @@ import numpy as np
cimport numpy as np
from numpy.core.multiarray import normalize_axis_index
+from .c_distributions cimport *
from libc cimport string
from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t,
int32_t, int64_t, INT64_MAX, SIZE_MAX)
@@ -26,117 +27,8 @@ from ._common cimport (POISSON_LAM_MAX, CONS_POSITIVE, CONS_NONE,
check_array_constraint, check_constraint, disc, discrete_broadcast_iii,
)
-
-cdef extern from "numpy/random/distributions.h":
-
- struct s_binomial_t:
- int has_binomial
- double psave
- int64_t nsave
- double r
- double q
- double fm
- int64_t m
- double p1
- double xm
- double xl
- double xr
- double c
- double laml
- double lamr
- double p2
- double p3
- double p4
-
- ctypedef s_binomial_t binomial_t
-
- 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
- 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
- double random_standard_gamma(bitgen_t *bitgen_state, double shape) nogil
-
- 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_normal_f(bitgen_t* bitgen_state) nogil
- float random_standard_gamma_f(bitgen_t *bitgen_state, float shape) nogil
-
- int64_t random_positive_int64(bitgen_t *bitgen_state) nogil
- int32_t random_positive_int32(bitgen_t *bitgen_state) nogil
- int64_t random_positive_int(bitgen_t *bitgen_state) nogil
- uint64_t random_uint(bitgen_t *bitgen_state) nogil
-
- double random_normal(bitgen_t *bitgen_state, double loc, double scale) nogil
-
- double random_gamma(bitgen_t *bitgen_state, double shape, double scale) nogil
- float random_gamma_f(bitgen_t *bitgen_state, float shape, float scale) nogil
-
- double random_exponential(bitgen_t *bitgen_state, double scale) nogil
- double random_uniform(bitgen_t *bitgen_state, double lower, double range) nogil
- 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_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
- double random_laplace(bitgen_t *bitgen_state, double loc, double scale) nogil
- double random_gumbel(bitgen_t *bitgen_state, double loc, double scale) nogil
- 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_noncentral_chisquare(bitgen_t *bitgen_state, double df,
- double nonc) nogil
- double random_noncentral_f(bitgen_t *bitgen_state, double dfnum,
- double dfden, double nonc) nogil
- double random_wald(bitgen_t *bitgen_state, double mean, double scale) nogil
- double random_vonmises(bitgen_t *bitgen_state, double mu, double kappa) nogil
- double random_triangular(bitgen_t *bitgen_state, double left, double mode,
- double right) nogil
-
- int64_t random_poisson(bitgen_t *bitgen_state, double lam) nogil
- int64_t random_negative_binomial(bitgen_t *bitgen_state, double n, double p) nogil
- int64_t random_binomial(bitgen_t *bitgen_state, double p, int64_t n, binomial_t *binomial) nogil
- int64_t random_logseries(bitgen_t *bitgen_state, double p) nogil
- int64_t random_geometric_search(bitgen_t *bitgen_state, double p) nogil
- int64_t random_geometric_inversion(bitgen_t *bitgen_state, double p) nogil
- int64_t random_geometric(bitgen_t *bitgen_state, double p) nogil
- int64_t random_zipf(bitgen_t *bitgen_state, double a) nogil
- int64_t random_hypergeometric(bitgen_t *bitgen_state, int64_t good, int64_t bad,
- int64_t sample) nogil
-
- uint64_t random_interval(bitgen_t *bitgen_state, uint64_t max) nogil
-
- # Generate random uint64 numbers in closed interval [off, off + rng].
- uint64_t random_bounded_uint64(bitgen_t *bitgen_state,
- uint64_t off, uint64_t rng,
- uint64_t mask, bint use_masked) nogil
-
- void random_multinomial(bitgen_t *bitgen_state, int64_t n, int64_t *mnix,
- double *pix, np.npy_intp d, binomial_t *binomial) nogil
-
- int random_multivariate_hypergeometric_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) nogil
- void random_multivariate_hypergeometric_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) nogil
-
np.import_array()
-
cdef int64_t _safe_sum_nonneg_int64(size_t num_colors, int64_t *colors):
"""
Sum the values in the array `colors`.
diff --git a/numpy/random/_bit_generator.pxd b/numpy/random/bit_generator.pxd
index bd5e47a20..bd5e47a20 100644
--- a/numpy/random/_bit_generator.pxd
+++ b/numpy/random/bit_generator.pxd
diff --git a/numpy/random/_bit_generator.pyx b/numpy/random/bit_generator.pyx
index 21d21e6bb..f145ec13d 100644
--- a/numpy/random/_bit_generator.pyx
+++ b/numpy/random/bit_generator.pyx
@@ -114,7 +114,7 @@ def _coerce_to_uint32_array(x):
Examples
--------
>>> import numpy as np
- >>> from numpy.random._bit_generator import _coerce_to_uint32_array
+ >>> from numpy.random.bit_generator import _coerce_to_uint32_array
>>> _coerce_to_uint32_array(12345)
array([12345], dtype=uint32)
>>> _coerce_to_uint32_array('12345')
diff --git a/numpy/random/c_distributions.pxd b/numpy/random/c_distributions.pxd
new file mode 100644
index 000000000..6f905edc1
--- /dev/null
+++ b/numpy/random/c_distributions.pxd
@@ -0,0 +1,114 @@
+#!python
+#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True, language_level=3
+from numpy cimport npy_intp
+
+from libc.stdint cimport (uint64_t, int32_t, int64_t)
+from numpy.random cimport bitgen_t
+
+cdef extern from "numpy/random/distributions.h":
+
+ struct s_binomial_t:
+ int has_binomial
+ double psave
+ int64_t nsave
+ double r
+ double q
+ double fm
+ int64_t m
+ double p1
+ double xm
+ double xl
+ double xr
+ double c
+ double laml
+ double lamr
+ double p2
+ double p3
+ double p4
+
+ ctypedef s_binomial_t binomial_t
+
+ double random_standard_uniform(bitgen_t *bitgen_state) nogil
+ void random_standard_uniform_fill(bitgen_t* bitgen_state, 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, npy_intp cnt, double *out) nogil
+ void random_standard_exponential_fill_f(bitgen_t *bitgen_state, npy_intp cnt, double *out) nogil
+ void random_standard_exponential_inv_fill(bitgen_t *bitgen_state, npy_intp cnt, double *out) nogil
+ void random_standard_exponential_inv_fill_f(bitgen_t *bitgen_state, npy_intp cnt, double *out) nogil
+ double random_standard_normal(bitgen_t* bitgen_state) nogil
+ void random_standard_normal_fill(bitgen_t *bitgen_state, npy_intp count, double *out) nogil
+ void random_standard_normal_fill_f(bitgen_t *bitgen_state, npy_intp count, float *out) nogil
+ double random_standard_gamma(bitgen_t *bitgen_state, double shape) nogil
+
+ float random_standard_uniform_f(bitgen_t *bitgen_state) nogil
+ void random_standard_uniform_fill_f(bitgen_t* bitgen_state, 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
+
+ int64_t random_positive_int64(bitgen_t *bitgen_state) nogil
+ int32_t random_positive_int32(bitgen_t *bitgen_state) nogil
+ int64_t random_positive_int(bitgen_t *bitgen_state) nogil
+ uint64_t random_uint(bitgen_t *bitgen_state) nogil
+
+ double random_normal(bitgen_t *bitgen_state, double loc, double scale) nogil
+
+ double random_gamma(bitgen_t *bitgen_state, double shape, double scale) nogil
+ float random_gamma_f(bitgen_t *bitgen_state, float shape, float scale) nogil
+
+ double random_exponential(bitgen_t *bitgen_state, double scale) nogil
+ double random_uniform(bitgen_t *bitgen_state, double lower, double range) nogil
+ 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_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
+ double random_laplace(bitgen_t *bitgen_state, double loc, double scale) nogil
+ double random_gumbel(bitgen_t *bitgen_state, double loc, double scale) nogil
+ 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_noncentral_chisquare(bitgen_t *bitgen_state, double df,
+ double nonc) nogil
+ double random_noncentral_f(bitgen_t *bitgen_state, double dfnum,
+ double dfden, double nonc) nogil
+ double random_wald(bitgen_t *bitgen_state, double mean, double scale) nogil
+ double random_vonmises(bitgen_t *bitgen_state, double mu, double kappa) nogil
+ double random_triangular(bitgen_t *bitgen_state, double left, double mode,
+ double right) nogil
+
+ int64_t random_poisson(bitgen_t *bitgen_state, double lam) nogil
+ int64_t random_negative_binomial(bitgen_t *bitgen_state, double n, double p) nogil
+ int64_t random_binomial(bitgen_t *bitgen_state, double p, int64_t n, binomial_t *binomial) nogil
+ int64_t random_logseries(bitgen_t *bitgen_state, double p) nogil
+ int64_t random_geometric_search(bitgen_t *bitgen_state, double p) nogil
+ int64_t random_geometric_inversion(bitgen_t *bitgen_state, double p) nogil
+ int64_t random_geometric(bitgen_t *bitgen_state, double p) nogil
+ int64_t random_zipf(bitgen_t *bitgen_state, double a) nogil
+ int64_t random_hypergeometric(bitgen_t *bitgen_state, int64_t good, int64_t bad,
+ int64_t sample) nogil
+
+ uint64_t random_interval(bitgen_t *bitgen_state, uint64_t max) nogil
+
+ # Generate random uint64 numbers in closed interval [off, off + rng].
+ uint64_t random_bounded_uint64(bitgen_t *bitgen_state,
+ uint64_t off, uint64_t rng,
+ uint64_t mask, bint use_masked) nogil
+
+ void random_multinomial(bitgen_t *bitgen_state, int64_t n, int64_t *mnix,
+ double *pix, npy_intp d, binomial_t *binomial) nogil
+
+ int random_multivariate_hypergeometric_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) nogil
+ void random_multivariate_hypergeometric_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) nogil
+
diff --git a/numpy/random/setup.py b/numpy/random/setup.py
index 42c00ee5e..5d6ff2c8b 100644
--- a/numpy/random/setup.py
+++ b/numpy/random/setup.py
@@ -35,8 +35,10 @@ def configuration(parent_package='', top_path=None):
config.add_data_dir('_examples')
EXTRA_LINK_ARGS = []
- # Math lib
- EXTRA_LIBRARIES = ['m'] if os.name != 'nt' else []
+ EXTRA_LIBRARIES = ['npyrandom']
+ if os.name != 'nt':
+ # Math lib
+ EXTRA_LIBRARIES.append('m')
# Some bit generators exclude GCC inlining
EXTRA_COMPILE_ARGS = ['-U__GNUC_GNU_INLINE__']
@@ -52,78 +54,88 @@ def configuration(parent_package='', top_path=None):
PCG64_DEFS = []
# One can force emulated 128-bit arithmetic if one wants.
#PCG64_DEFS += [('PCG_FORCE_EMULATED_128BIT_MATH', '1')]
+ depends = ['__init__.pxd', 'c_distributions.pxd', 'bit_generator.pxd']
+
+ # npyrandom - a library like npymath
+ npyrandom_sources = [
+ 'src/distributions/logfactorial.c',
+ 'src/distributions/distributions.c',
+ 'src/distributions/random_mvhg_count.c',
+ 'src/distributions/random_mvhg_marginals.c',
+ 'src/distributions/random_hypergeometric.c',
+ ]
+ config.add_installed_library('npyrandom',
+ sources=npyrandom_sources,
+ install_dir='lib',
+ build_info={
+ 'include_dirs' : [], # empty list required for creating npyrandom.h
+ 'extra_compiler_args' : (['/GL-'] if is_msvc else []),
+ })
for gen in ['mt19937']:
# gen.pyx, src/gen/gen.c, src/gen/gen-jump.c
- config.add_extension('_{0}'.format(gen),
- sources=['_{0}.c'.format(gen),
- 'src/{0}/{0}.c'.format(gen),
- 'src/{0}/{0}-jump.c'.format(gen)],
+ config.add_extension(f'_{gen}',
+ sources=[f'_{gen}.c',
+ f'src/{gen}/{gen}.c',
+ f'src/{gen}/{gen}-jump.c'],
include_dirs=['.', 'src', join('src', gen)],
libraries=EXTRA_LIBRARIES,
extra_compile_args=EXTRA_COMPILE_ARGS,
extra_link_args=EXTRA_LINK_ARGS,
- depends=['_%s.pyx' % gen],
+ depends=depends + [f'_{gen}.pyx'],
define_macros=defs,
)
for gen in ['philox', 'pcg64', 'sfc64']:
# gen.pyx, src/gen/gen.c
_defs = defs + PCG64_DEFS if gen == 'pcg64' else defs
- config.add_extension('_{0}'.format(gen),
- sources=['_{0}.c'.format(gen),
- 'src/{0}/{0}.c'.format(gen)],
+ config.add_extension(f'_{gen}',
+ sources=[f'_{gen}.c',
+ f'src/{gen}/{gen}.c'],
include_dirs=['.', 'src', join('src', gen)],
libraries=EXTRA_LIBRARIES,
extra_compile_args=EXTRA_COMPILE_ARGS,
extra_link_args=EXTRA_LINK_ARGS,
- depends=['_%s.pyx' % gen, '_bit_generator.pyx',
- '_bit_generator.pxd'],
+ depends=depends + [f'_{gen}.pyx',
+ 'bit_generator.pyx', 'bit_generator.pxd'],
define_macros=_defs,
)
- for gen in ['_common', '_bit_generator']:
+ for gen in ['_common', 'bit_generator']:
# gen.pyx
config.add_extension(gen,
- sources=['{0}.c'.format(gen)],
+ sources=[f'{gen}.c'],
libraries=EXTRA_LIBRARIES,
extra_compile_args=EXTRA_COMPILE_ARGS,
extra_link_args=EXTRA_LINK_ARGS,
include_dirs=['.', 'src'],
- depends=['%s.pyx' % gen, '%s.pxd' % gen,],
+ depends=depends + [f'{gen}.pyx', f'{gen}.pxd',],
define_macros=defs,
)
- config.add_data_files('{0}.pxd'.format(gen))
- other_srcs = [
- 'src/distributions/logfactorial.c',
- 'src/distributions/distributions.c',
- 'src/distributions/random_mvhg_count.c',
- 'src/distributions/random_mvhg_marginals.c',
- 'src/distributions/random_hypergeometric.c',
- ]
+ config.add_data_files('{gen}.pxd')
for gen in ['_generator', '_bounded_integers']:
# gen.pyx, src/distributions/distributions.c
config.add_extension(gen,
- sources=['{0}.c'.format(gen)] + other_srcs,
+ sources=[f'{gen}.c'],
libraries=EXTRA_LIBRARIES,
extra_compile_args=EXTRA_COMPILE_ARGS,
include_dirs=['.', 'src'],
extra_link_args=EXTRA_LINK_ARGS,
- depends=['%s.pyx' % gen],
+ depends=depends + [f'{gen}.pyx'],
define_macros=defs,
)
config.add_data_files('_bounded_integers.pxd')
config.add_extension('mtrand',
sources=['mtrand.c',
'src/legacy/legacy-distributions.c',
- 'src/distributions/logfactorial.c',
- 'src/distributions/distributions.c'],
+ 'src/distributions/distributions.c',
+ ],
include_dirs=['.', 'src', 'src/legacy'],
- libraries=EXTRA_LIBRARIES,
+ libraries=['m'] if os.name != 'nt' else [],
extra_compile_args=EXTRA_COMPILE_ARGS,
extra_link_args=EXTRA_LINK_ARGS,
- depends=['mtrand.pyx'],
+ depends=depends + ['mtrand.pyx'],
define_macros=defs + LEGACY_DEFS,
)
- config.add_data_files('__init__.pxd')
+ config.add_data_files(*depends)
return config
diff --git a/numpy/random/tests/test_direct.py b/numpy/random/tests/test_direct.py
index 4fa69a402..dad12c8a8 100644
--- a/numpy/random/tests/test_direct.py
+++ b/numpy/random/tests/test_direct.py
@@ -127,7 +127,7 @@ def gauss_from_uint(x, n, bits):
return gauss[:n]
def test_seedsequence():
- from numpy.random._bit_generator import (ISeedSequence,
+ from numpy.random.bit_generator import (ISeedSequence,
ISpawnableSeedSequence,
SeedlessSeedSequence)
diff --git a/numpy/random/tests/test_extending.py b/numpy/random/tests/test_extending.py
index 64b8803dd..f7efafba9 100644
--- a/numpy/random/tests/test_extending.py
+++ b/numpy/random/tests/test_extending.py
@@ -4,6 +4,7 @@ import shutil
import subprocess
import sys
import warnings
+import numpy as np
try:
import cffi
@@ -42,10 +43,37 @@ else:
@pytest.mark.skipif(cython is None, reason="requires cython")
@pytest.mark.slow
def test_cython(tmp_path):
- examples = os.path.join(os.path.dirname(__file__), '..', '_examples')
- shutil.copytree(examples, tmp_path / '_examples')
- subprocess.check_call([sys.executable, 'setup.py', 'build'],
- cwd=str(tmp_path / '_examples' / 'cython'))
+ srcdir = os.path.join(os.path.dirname(__file__), '..')
+ shutil.copytree(srcdir, tmp_path / 'random')
+ # build the examples and "install" them into a temporary directory
+ env = os.environ.copy()
+ subprocess.check_call([sys.executable, 'setup.py', 'build', 'install',
+ '--prefix', str(tmp_path / 'installdir'),
+ '--single-version-externally-managed',
+ '--record', str(tmp_path/ 'tmp_install_log.txt'),
+ ],
+ cwd=str(tmp_path / 'random' / '_examples' / 'cython'),
+ env=env)
+ # get the path to the so's
+ so1 = so2 = None
+ with open(tmp_path /'tmp_install_log.txt') as fid:
+ for line in fid:
+ if 'extending.' in line:
+ so1 = line.strip()
+ if 'extending_distributions' in line:
+ so2 = line.strip()
+ assert so1 is not None
+ assert so2 is not None
+ # import the so's without adding the directory to sys.path
+ from importlib.machinery import ExtensionFileLoader
+ extending = ExtensionFileLoader('extending', so1).load_module()
+ extending_distributions = ExtensionFileLoader('extending_distributions', so2).load_module()
+
+ # actually test the cython c-extension
+ from numpy.random import PCG64
+ values = extending_distributions.uniforms_ex(PCG64(0), 10, 'd')
+ assert values.shape == (10,)
+ assert values.dtype == np.float64
@pytest.mark.skipif(numba is None or cffi is None,
reason="requires numba and cffi")
diff --git a/numpy/tests/test_public_api.py b/numpy/tests/test_public_api.py
index 27ff87f49..fb7ec5d83 100644
--- a/numpy/tests/test_public_api.py
+++ b/numpy/tests/test_public_api.py
@@ -298,6 +298,7 @@ PRIVATE_BUT_PRESENT_MODULES = ['numpy.' + s for s in [
"matrixlib",
"matrixlib.defmatrix",
"random.mtrand",
+ "random.bit_generator",
"testing.print_coercion_tables",
"testing.utils",
]]